celleb_scc_pciex.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548
  1. /*
  2. * Support for Celleb PCI-Express.
  3. *
  4. * (C) Copyright 2007-2008 TOSHIBA CORPORATION
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. */
  20. #undef DEBUG
  21. #include <linux/kernel.h>
  22. #include <linux/pci.h>
  23. #include <linux/string.h>
  24. #include <linux/init.h>
  25. #include <linux/bootmem.h>
  26. #include <linux/delay.h>
  27. #include <linux/interrupt.h>
  28. #include <asm/io.h>
  29. #include <asm/irq.h>
  30. #include <asm/iommu.h>
  31. #include <asm/byteorder.h>
  32. #include "celleb_scc.h"
  33. #include "celleb_pci.h"
  34. #define PEX_IN(base, off) in_be32((void __iomem *)(base) + (off))
  35. #define PEX_OUT(base, off, data) out_be32((void __iomem *)(base) + (off), (data))
  36. static void scc_pciex_io_flush(struct iowa_bus *bus)
  37. {
  38. (void)PEX_IN(bus->phb->cfg_addr, PEXDMRDEN0);
  39. }
  40. /*
  41. * Memory space access to device on PCIEX
  42. */
  43. #define PCIEX_MMIO_READ(name, ret) \
  44. static ret scc_pciex_##name(const PCI_IO_ADDR addr) \
  45. { \
  46. ret val = __do_##name(addr); \
  47. scc_pciex_io_flush(iowa_mem_find_bus(addr)); \
  48. return val; \
  49. }
  50. #define PCIEX_MMIO_READ_STR(name) \
  51. static void scc_pciex_##name(const PCI_IO_ADDR addr, void *buf, \
  52. unsigned long count) \
  53. { \
  54. __do_##name(addr, buf, count); \
  55. scc_pciex_io_flush(iowa_mem_find_bus(addr)); \
  56. }
  57. PCIEX_MMIO_READ(readb, u8)
  58. PCIEX_MMIO_READ(readw, u16)
  59. PCIEX_MMIO_READ(readl, u32)
  60. PCIEX_MMIO_READ(readq, u64)
  61. PCIEX_MMIO_READ(readw_be, u16)
  62. PCIEX_MMIO_READ(readl_be, u32)
  63. PCIEX_MMIO_READ(readq_be, u64)
  64. PCIEX_MMIO_READ_STR(readsb)
  65. PCIEX_MMIO_READ_STR(readsw)
  66. PCIEX_MMIO_READ_STR(readsl)
  67. static void scc_pciex_memcpy_fromio(void *dest, const PCI_IO_ADDR src,
  68. unsigned long n)
  69. {
  70. __do_memcpy_fromio(dest, src, n);
  71. scc_pciex_io_flush(iowa_mem_find_bus(src));
  72. }
  73. /*
  74. * I/O port access to devices on PCIEX.
  75. */
  76. static inline unsigned long get_bus_address(struct pci_controller *phb,
  77. unsigned long port)
  78. {
  79. return port - ((unsigned long)(phb->io_base_virt) - _IO_BASE);
  80. }
  81. static u32 scc_pciex_read_port(struct pci_controller *phb,
  82. unsigned long port, int size)
  83. {
  84. unsigned int byte_enable;
  85. unsigned int cmd, shift;
  86. unsigned long addr;
  87. u32 data, ret;
  88. BUG_ON(((port & 0x3ul) + size) > 4);
  89. addr = get_bus_address(phb, port);
  90. shift = addr & 0x3ul;
  91. byte_enable = ((1 << size) - 1) << shift;
  92. cmd = PEXDCMND_IO_READ | (byte_enable << PEXDCMND_BYTE_EN_SHIFT);
  93. PEX_OUT(phb->cfg_addr, PEXDADRS, (addr & ~0x3ul));
  94. PEX_OUT(phb->cfg_addr, PEXDCMND, cmd);
  95. data = PEX_IN(phb->cfg_addr, PEXDRDATA);
  96. ret = (data >> (shift * 8)) & (0xFFFFFFFF >> ((4 - size) * 8));
  97. pr_debug("PCIEX:PIO READ:port=0x%lx, addr=0x%lx, size=%d, be=%x,"
  98. " cmd=%x, data=%x, ret=%x\n", port, addr, size, byte_enable,
  99. cmd, data, ret);
  100. return ret;
  101. }
  102. static void scc_pciex_write_port(struct pci_controller *phb,
  103. unsigned long port, int size, u32 val)
  104. {
  105. unsigned int byte_enable;
  106. unsigned int cmd, shift;
  107. unsigned long addr;
  108. u32 data;
  109. BUG_ON(((port & 0x3ul) + size) > 4);
  110. addr = get_bus_address(phb, port);
  111. shift = addr & 0x3ul;
  112. byte_enable = ((1 << size) - 1) << shift;
  113. cmd = PEXDCMND_IO_WRITE | (byte_enable << PEXDCMND_BYTE_EN_SHIFT);
  114. data = (val & (0xFFFFFFFF >> (4 - size) * 8)) << (shift * 8);
  115. PEX_OUT(phb->cfg_addr, PEXDADRS, (addr & ~0x3ul));
  116. PEX_OUT(phb->cfg_addr, PEXDCMND, cmd);
  117. PEX_OUT(phb->cfg_addr, PEXDWDATA, data);
  118. pr_debug("PCIEX:PIO WRITE:port=0x%lx, addr=%lx, size=%d, val=%x,"
  119. " be=%x, cmd=%x, data=%x\n", port, addr, size, val,
  120. byte_enable, cmd, data);
  121. }
  122. static u8 __scc_pciex_inb(struct pci_controller *phb, unsigned long port)
  123. {
  124. return (u8)scc_pciex_read_port(phb, port, 1);
  125. }
  126. static u16 __scc_pciex_inw(struct pci_controller *phb, unsigned long port)
  127. {
  128. u32 data;
  129. if ((port & 0x3ul) < 3)
  130. data = scc_pciex_read_port(phb, port, 2);
  131. else {
  132. u32 d1 = scc_pciex_read_port(phb, port, 1);
  133. u32 d2 = scc_pciex_read_port(phb, port + 1, 1);
  134. data = d1 | (d2 << 8);
  135. }
  136. return (u16)data;
  137. }
  138. static u32 __scc_pciex_inl(struct pci_controller *phb, unsigned long port)
  139. {
  140. unsigned int mod = port & 0x3ul;
  141. u32 data;
  142. if (mod == 0)
  143. data = scc_pciex_read_port(phb, port, 4);
  144. else {
  145. u32 d1 = scc_pciex_read_port(phb, port, 4 - mod);
  146. u32 d2 = scc_pciex_read_port(phb, port + 1, mod);
  147. data = d1 | (d2 << (mod * 8));
  148. }
  149. return data;
  150. }
  151. static void __scc_pciex_outb(struct pci_controller *phb,
  152. u8 val, unsigned long port)
  153. {
  154. scc_pciex_write_port(phb, port, 1, (u32)val);
  155. }
  156. static void __scc_pciex_outw(struct pci_controller *phb,
  157. u16 val, unsigned long port)
  158. {
  159. if ((port & 0x3ul) < 3)
  160. scc_pciex_write_port(phb, port, 2, (u32)val);
  161. else {
  162. u32 d1 = val & 0x000000FF;
  163. u32 d2 = (val & 0x0000FF00) >> 8;
  164. scc_pciex_write_port(phb, port, 1, d1);
  165. scc_pciex_write_port(phb, port + 1, 1, d2);
  166. }
  167. }
  168. static void __scc_pciex_outl(struct pci_controller *phb,
  169. u32 val, unsigned long port)
  170. {
  171. unsigned int mod = port & 0x3ul;
  172. if (mod == 0)
  173. scc_pciex_write_port(phb, port, 4, val);
  174. else {
  175. u32 d1 = val & (0xFFFFFFFFul >> (mod * 8));
  176. u32 d2 = val >> ((4 - mod) * 8);
  177. scc_pciex_write_port(phb, port, 4 - mod, d1);
  178. scc_pciex_write_port(phb, port + 1, mod, d2);
  179. }
  180. }
  181. #define PCIEX_PIO_FUNC(size, name) \
  182. static u##size scc_pciex_in##name(unsigned long port) \
  183. { \
  184. struct iowa_bus *bus = iowa_pio_find_bus(port); \
  185. u##size data = __scc_pciex_in##name(bus->phb, port); \
  186. scc_pciex_io_flush(bus); \
  187. return data; \
  188. } \
  189. static void scc_pciex_ins##name(unsigned long p, void *b, unsigned long c) \
  190. { \
  191. struct iowa_bus *bus = iowa_pio_find_bus(p); \
  192. __le##size *dst = b; \
  193. for (; c != 0; c--, dst++) \
  194. *dst = cpu_to_le##size(__scc_pciex_in##name(bus->phb, p)); \
  195. scc_pciex_io_flush(bus); \
  196. } \
  197. static void scc_pciex_out##name(u##size val, unsigned long port) \
  198. { \
  199. struct iowa_bus *bus = iowa_pio_find_bus(port); \
  200. __scc_pciex_out##name(bus->phb, val, port); \
  201. } \
  202. static void scc_pciex_outs##name(unsigned long p, const void *b, \
  203. unsigned long c) \
  204. { \
  205. struct iowa_bus *bus = iowa_pio_find_bus(p); \
  206. const __le##size *src = b; \
  207. for (; c != 0; c--, src++) \
  208. __scc_pciex_out##name(bus->phb, le##size##_to_cpu(*src), p); \
  209. }
  210. #define __le8 u8
  211. #define cpu_to_le8(x) (x)
  212. #define le8_to_cpu(x) (x)
  213. PCIEX_PIO_FUNC(8, b)
  214. PCIEX_PIO_FUNC(16, w)
  215. PCIEX_PIO_FUNC(32, l)
  216. static struct ppc_pci_io scc_pciex_ops = {
  217. .readb = scc_pciex_readb,
  218. .readw = scc_pciex_readw,
  219. .readl = scc_pciex_readl,
  220. .readq = scc_pciex_readq,
  221. .readw_be = scc_pciex_readw_be,
  222. .readl_be = scc_pciex_readl_be,
  223. .readq_be = scc_pciex_readq_be,
  224. .readsb = scc_pciex_readsb,
  225. .readsw = scc_pciex_readsw,
  226. .readsl = scc_pciex_readsl,
  227. .memcpy_fromio = scc_pciex_memcpy_fromio,
  228. .inb = scc_pciex_inb,
  229. .inw = scc_pciex_inw,
  230. .inl = scc_pciex_inl,
  231. .outb = scc_pciex_outb,
  232. .outw = scc_pciex_outw,
  233. .outl = scc_pciex_outl,
  234. .insb = scc_pciex_insb,
  235. .insw = scc_pciex_insw,
  236. .insl = scc_pciex_insl,
  237. .outsb = scc_pciex_outsb,
  238. .outsw = scc_pciex_outsw,
  239. .outsl = scc_pciex_outsl,
  240. };
  241. static int __init scc_pciex_iowa_init(struct iowa_bus *bus, void *data)
  242. {
  243. dma_addr_t dummy_page_da;
  244. void *dummy_page_va;
  245. dummy_page_va = kmalloc(PAGE_SIZE, GFP_KERNEL);
  246. if (!dummy_page_va) {
  247. pr_err("PCIEX:Alloc dummy_page_va failed\n");
  248. return -1;
  249. }
  250. dummy_page_da = dma_map_single(bus->phb->parent, dummy_page_va,
  251. PAGE_SIZE, DMA_FROM_DEVICE);
  252. if (dma_mapping_error(bus->phb->parent, dummy_page_da)) {
  253. pr_err("PCIEX:Map dummy page failed.\n");
  254. kfree(dummy_page_va);
  255. return -1;
  256. }
  257. PEX_OUT(bus->phb->cfg_addr, PEXDMRDADR0, dummy_page_da);
  258. return 0;
  259. }
  260. /*
  261. * config space access
  262. */
  263. #define MK_PEXDADRS(bus_no, dev_no, func_no, addr) \
  264. ((uint32_t)(((addr) & ~0x3UL) | \
  265. ((bus_no) << PEXDADRS_BUSNO_SHIFT) | \
  266. ((dev_no) << PEXDADRS_DEVNO_SHIFT) | \
  267. ((func_no) << PEXDADRS_FUNCNO_SHIFT)))
  268. #define MK_PEXDCMND_BYTE_EN(addr, size) \
  269. ((((0x1 << (size))-1) << ((addr) & 0x3)) << PEXDCMND_BYTE_EN_SHIFT)
  270. #define MK_PEXDCMND(cmd, addr, size) ((cmd) | MK_PEXDCMND_BYTE_EN(addr, size))
  271. static uint32_t config_read_pciex_dev(unsigned int __iomem *base,
  272. uint64_t bus_no, uint64_t dev_no, uint64_t func_no,
  273. uint64_t off, uint64_t size)
  274. {
  275. uint32_t ret;
  276. uint32_t addr, cmd;
  277. addr = MK_PEXDADRS(bus_no, dev_no, func_no, off);
  278. cmd = MK_PEXDCMND(PEXDCMND_CONFIG_READ, off, size);
  279. PEX_OUT(base, PEXDADRS, addr);
  280. PEX_OUT(base, PEXDCMND, cmd);
  281. ret = (PEX_IN(base, PEXDRDATA)
  282. >> ((off & (4-size)) * 8)) & ((0x1 << (size * 8)) - 1);
  283. return ret;
  284. }
  285. static void config_write_pciex_dev(unsigned int __iomem *base, uint64_t bus_no,
  286. uint64_t dev_no, uint64_t func_no, uint64_t off, uint64_t size,
  287. uint32_t data)
  288. {
  289. uint32_t addr, cmd;
  290. addr = MK_PEXDADRS(bus_no, dev_no, func_no, off);
  291. cmd = MK_PEXDCMND(PEXDCMND_CONFIG_WRITE, off, size);
  292. PEX_OUT(base, PEXDADRS, addr);
  293. PEX_OUT(base, PEXDCMND, cmd);
  294. PEX_OUT(base, PEXDWDATA,
  295. (data & ((0x1 << (size * 8)) - 1)) << ((off & (4-size)) * 8));
  296. }
  297. #define MK_PEXCADRS_BYTE_EN(off, len) \
  298. ((((0x1 << (len)) - 1) << ((off) & 0x3)) << PEXCADRS_BYTE_EN_SHIFT)
  299. #define MK_PEXCADRS(cmd, addr, size) \
  300. ((cmd) | MK_PEXCADRS_BYTE_EN(addr, size) | ((addr) & ~0x3))
  301. static uint32_t config_read_pciex_rc(unsigned int __iomem *base,
  302. uint32_t where, uint32_t size)
  303. {
  304. PEX_OUT(base, PEXCADRS, MK_PEXCADRS(PEXCADRS_CMD_READ, where, size));
  305. return (PEX_IN(base, PEXCRDATA)
  306. >> ((where & (4 - size)) * 8)) & ((0x1 << (size * 8)) - 1);
  307. }
  308. static void config_write_pciex_rc(unsigned int __iomem *base, uint32_t where,
  309. uint32_t size, uint32_t val)
  310. {
  311. uint32_t data;
  312. data = (val & ((0x1 << (size * 8)) - 1)) << ((where & (4 - size)) * 8);
  313. PEX_OUT(base, PEXCADRS, MK_PEXCADRS(PEXCADRS_CMD_WRITE, where, size));
  314. PEX_OUT(base, PEXCWDATA, data);
  315. }
  316. /* Interfaces */
  317. /* Note: Work-around
  318. * On SCC PCIEXC, one device is seen on all 32 dev_no.
  319. * As SCC PCIEXC can have only one device on the bus, we look only one dev_no.
  320. * (dev_no = 1)
  321. */
  322. static int scc_pciex_read_config(struct pci_bus *bus, unsigned int devfn,
  323. int where, int size, unsigned int *val)
  324. {
  325. struct device_node *dn;
  326. struct pci_controller *phb;
  327. dn = bus->sysdata;
  328. phb = pci_find_hose_for_OF_device(dn);
  329. if (bus->number == phb->first_busno && PCI_SLOT(devfn) != 1) {
  330. *val = ~0;
  331. return PCIBIOS_DEVICE_NOT_FOUND;
  332. }
  333. if (bus->number == 0 && PCI_SLOT(devfn) == 0)
  334. *val = config_read_pciex_rc(phb->cfg_addr, where, size);
  335. else
  336. *val = config_read_pciex_dev(phb->cfg_addr, bus->number,
  337. PCI_SLOT(devfn), PCI_FUNC(devfn), where, size);
  338. return PCIBIOS_SUCCESSFUL;
  339. }
  340. static int scc_pciex_write_config(struct pci_bus *bus, unsigned int devfn,
  341. int where, int size, unsigned int val)
  342. {
  343. struct device_node *dn;
  344. struct pci_controller *phb;
  345. dn = bus->sysdata;
  346. phb = pci_find_hose_for_OF_device(dn);
  347. if (bus->number == phb->first_busno && PCI_SLOT(devfn) != 1)
  348. return PCIBIOS_DEVICE_NOT_FOUND;
  349. if (bus->number == 0 && PCI_SLOT(devfn) == 0)
  350. config_write_pciex_rc(phb->cfg_addr, where, size, val);
  351. else
  352. config_write_pciex_dev(phb->cfg_addr, bus->number,
  353. PCI_SLOT(devfn), PCI_FUNC(devfn), where, size, val);
  354. return PCIBIOS_SUCCESSFUL;
  355. }
  356. static struct pci_ops scc_pciex_pci_ops = {
  357. scc_pciex_read_config,
  358. scc_pciex_write_config,
  359. };
  360. static void pciex_clear_intr_all(unsigned int __iomem *base)
  361. {
  362. PEX_OUT(base, PEXAERRSTS, 0xffffffff);
  363. PEX_OUT(base, PEXPRERRSTS, 0xffffffff);
  364. PEX_OUT(base, PEXINTSTS, 0xffffffff);
  365. }
  366. #if 0
  367. static void pciex_disable_intr_all(unsigned int *base)
  368. {
  369. PEX_OUT(base, PEXINTMASK, 0x0);
  370. PEX_OUT(base, PEXAERRMASK, 0x0);
  371. PEX_OUT(base, PEXPRERRMASK, 0x0);
  372. PEX_OUT(base, PEXVDMASK, 0x0);
  373. }
  374. #endif
  375. static void pciex_enable_intr_all(unsigned int __iomem *base)
  376. {
  377. PEX_OUT(base, PEXINTMASK, 0x0000e7f1);
  378. PEX_OUT(base, PEXAERRMASK, 0x03ff01ff);
  379. PEX_OUT(base, PEXPRERRMASK, 0x0001010f);
  380. PEX_OUT(base, PEXVDMASK, 0x00000001);
  381. }
  382. static void pciex_check_status(unsigned int __iomem *base)
  383. {
  384. uint32_t err = 0;
  385. uint32_t intsts, aerr, prerr, rcvcp, lenerr;
  386. uint32_t maea, maec;
  387. intsts = PEX_IN(base, PEXINTSTS);
  388. aerr = PEX_IN(base, PEXAERRSTS);
  389. prerr = PEX_IN(base, PEXPRERRSTS);
  390. rcvcp = PEX_IN(base, PEXRCVCPLIDA);
  391. lenerr = PEX_IN(base, PEXLENERRIDA);
  392. if (intsts || aerr || prerr || rcvcp || lenerr)
  393. err = 1;
  394. pr_info("PCEXC interrupt!!\n");
  395. pr_info("PEXINTSTS :0x%08x\n", intsts);
  396. pr_info("PEXAERRSTS :0x%08x\n", aerr);
  397. pr_info("PEXPRERRSTS :0x%08x\n", prerr);
  398. pr_info("PEXRCVCPLIDA :0x%08x\n", rcvcp);
  399. pr_info("PEXLENERRIDA :0x%08x\n", lenerr);
  400. /* print detail of Protection Error */
  401. if (intsts & 0x00004000) {
  402. uint32_t i, n;
  403. for (i = 0; i < 4; i++) {
  404. n = 1 << i;
  405. if (prerr & n) {
  406. maea = PEX_IN(base, PEXMAEA(i));
  407. maec = PEX_IN(base, PEXMAEC(i));
  408. pr_info("PEXMAEC%d :0x%08x\n", i, maec);
  409. pr_info("PEXMAEA%d :0x%08x\n", i, maea);
  410. }
  411. }
  412. }
  413. if (err)
  414. pciex_clear_intr_all(base);
  415. }
  416. static irqreturn_t pciex_handle_internal_irq(int irq, void *dev_id)
  417. {
  418. struct pci_controller *phb = dev_id;
  419. pr_debug("PCIEX:pciex_handle_internal_irq(irq=%d)\n", irq);
  420. BUG_ON(phb->cfg_addr == NULL);
  421. pciex_check_status(phb->cfg_addr);
  422. return IRQ_HANDLED;
  423. }
  424. static __init int celleb_setup_pciex(struct device_node *node,
  425. struct pci_controller *phb)
  426. {
  427. struct resource r;
  428. struct of_irq oirq;
  429. int virq;
  430. /* SMMIO registers; used inside this file */
  431. if (of_address_to_resource(node, 0, &r)) {
  432. pr_err("PCIEXC:Failed to get config resource.\n");
  433. return 1;
  434. }
  435. phb->cfg_addr = ioremap(r.start, r.end - r.start + 1);
  436. if (!phb->cfg_addr) {
  437. pr_err("PCIEXC:Failed to remap SMMIO region.\n");
  438. return 1;
  439. }
  440. /* Not use cfg_data, cmd and data regs are near address reg */
  441. phb->cfg_data = NULL;
  442. /* set pci_ops */
  443. phb->ops = &scc_pciex_pci_ops;
  444. /* internal interrupt handler */
  445. if (of_irq_map_one(node, 1, &oirq)) {
  446. pr_err("PCIEXC:Failed to map irq\n");
  447. goto error;
  448. }
  449. virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
  450. oirq.size);
  451. if (request_irq(virq, pciex_handle_internal_irq,
  452. IRQF_DISABLED, "pciex", (void *)phb)) {
  453. pr_err("PCIEXC:Failed to request irq\n");
  454. goto error;
  455. }
  456. /* enable all interrupts */
  457. pciex_clear_intr_all(phb->cfg_addr);
  458. pciex_enable_intr_all(phb->cfg_addr);
  459. /* MSI: TBD */
  460. return 0;
  461. error:
  462. phb->cfg_data = NULL;
  463. if (phb->cfg_addr)
  464. iounmap(phb->cfg_addr);
  465. phb->cfg_addr = NULL;
  466. return 1;
  467. }
  468. struct celleb_phb_spec celleb_pciex_spec __initdata = {
  469. .setup = celleb_setup_pciex,
  470. .ops = &scc_pciex_ops,
  471. .iowa_init = &scc_pciex_iowa_init,
  472. };