cpm1.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
  1. /*
  2. * General Purpose functions for the global management of the
  3. * Communication Processor Module.
  4. * Copyright (c) 1997 Dan error_act (dmalek@jlc.net)
  5. *
  6. * In addition to the individual control of the communication
  7. * channels, there are a few functions that globally affect the
  8. * communication processor.
  9. *
  10. * Buffer descriptors must be allocated from the dual ported memory
  11. * space. The allocator for that is here. When the communication
  12. * process is reset, we reclaim the memory available. There is
  13. * currently no deallocator for this memory.
  14. * The amount of space available is platform dependent. On the
  15. * MBX, the EPPC software loads additional microcode into the
  16. * communication processor, and uses some of the DP ram for this
  17. * purpose. Current, the first 512 bytes and the last 256 bytes of
  18. * memory are used. Right now I am conservative and only use the
  19. * memory that can never be used for microcode. If there are
  20. * applications that require more DP ram, we can expand the boundaries
  21. * but then we have to be careful of any downloaded microcode.
  22. */
  23. #include <linux/errno.h>
  24. #include <linux/sched.h>
  25. #include <linux/kernel.h>
  26. #include <linux/dma-mapping.h>
  27. #include <linux/param.h>
  28. #include <linux/string.h>
  29. #include <linux/mm.h>
  30. #include <linux/interrupt.h>
  31. #include <linux/irq.h>
  32. #include <linux/module.h>
  33. #include <asm/page.h>
  34. #include <asm/pgtable.h>
  35. #include <asm/8xx_immap.h>
  36. #include <asm/cpm1.h>
  37. #include <asm/io.h>
  38. #include <asm/tlbflush.h>
  39. #include <asm/rheap.h>
  40. #include <asm/prom.h>
  41. #include <asm/cpm.h>
  42. #include <asm/fs_pd.h>
  43. #define CPM_MAP_SIZE (0x4000)
  44. #ifndef CONFIG_PPC_CPM_NEW_BINDING
  45. static void m8xx_cpm_dpinit(void);
  46. #endif
  47. cpm8xx_t __iomem *cpmp; /* Pointer to comm processor space */
  48. immap_t __iomem *mpc8xx_immr;
  49. static cpic8xx_t __iomem *cpic_reg;
  50. static struct irq_host *cpm_pic_host;
  51. static void cpm_mask_irq(unsigned int irq)
  52. {
  53. unsigned int cpm_vec = (unsigned int)irq_map[irq].hwirq;
  54. clrbits32(&cpic_reg->cpic_cimr, (1 << cpm_vec));
  55. }
  56. static void cpm_unmask_irq(unsigned int irq)
  57. {
  58. unsigned int cpm_vec = (unsigned int)irq_map[irq].hwirq;
  59. setbits32(&cpic_reg->cpic_cimr, (1 << cpm_vec));
  60. }
  61. static void cpm_end_irq(unsigned int irq)
  62. {
  63. unsigned int cpm_vec = (unsigned int)irq_map[irq].hwirq;
  64. out_be32(&cpic_reg->cpic_cisr, (1 << cpm_vec));
  65. }
  66. static struct irq_chip cpm_pic = {
  67. .typename = " CPM PIC ",
  68. .mask = cpm_mask_irq,
  69. .unmask = cpm_unmask_irq,
  70. .eoi = cpm_end_irq,
  71. };
  72. int cpm_get_irq(void)
  73. {
  74. int cpm_vec;
  75. /* Get the vector by setting the ACK bit and then reading
  76. * the register.
  77. */
  78. out_be16(&cpic_reg->cpic_civr, 1);
  79. cpm_vec = in_be16(&cpic_reg->cpic_civr);
  80. cpm_vec >>= 11;
  81. return irq_linear_revmap(cpm_pic_host, cpm_vec);
  82. }
  83. static int cpm_pic_host_map(struct irq_host *h, unsigned int virq,
  84. irq_hw_number_t hw)
  85. {
  86. pr_debug("cpm_pic_host_map(%d, 0x%lx)\n", virq, hw);
  87. get_irq_desc(virq)->status |= IRQ_LEVEL;
  88. set_irq_chip_and_handler(virq, &cpm_pic, handle_fasteoi_irq);
  89. return 0;
  90. }
  91. /* The CPM can generate the error interrupt when there is a race condition
  92. * between generating and masking interrupts. All we have to do is ACK it
  93. * and return. This is a no-op function so we don't need any special
  94. * tests in the interrupt handler.
  95. */
  96. static irqreturn_t cpm_error_interrupt(int irq, void *dev)
  97. {
  98. return IRQ_HANDLED;
  99. }
  100. static struct irqaction cpm_error_irqaction = {
  101. .handler = cpm_error_interrupt,
  102. .mask = CPU_MASK_NONE,
  103. .name = "error",
  104. };
  105. static struct irq_host_ops cpm_pic_host_ops = {
  106. .map = cpm_pic_host_map,
  107. };
  108. unsigned int cpm_pic_init(void)
  109. {
  110. struct device_node *np = NULL;
  111. struct resource res;
  112. unsigned int sirq = NO_IRQ, hwirq, eirq;
  113. int ret;
  114. pr_debug("cpm_pic_init\n");
  115. np = of_find_compatible_node(NULL, NULL, "fsl,cpm1-pic");
  116. if (np == NULL)
  117. np = of_find_compatible_node(NULL, "cpm-pic", "CPM");
  118. if (np == NULL) {
  119. printk(KERN_ERR "CPM PIC init: can not find cpm-pic node\n");
  120. return sirq;
  121. }
  122. ret = of_address_to_resource(np, 0, &res);
  123. if (ret)
  124. goto end;
  125. cpic_reg = ioremap(res.start, res.end - res.start + 1);
  126. if (cpic_reg == NULL)
  127. goto end;
  128. sirq = irq_of_parse_and_map(np, 0);
  129. if (sirq == NO_IRQ)
  130. goto end;
  131. /* Initialize the CPM interrupt controller. */
  132. hwirq = (unsigned int)irq_map[sirq].hwirq;
  133. out_be32(&cpic_reg->cpic_cicr,
  134. (CICR_SCD_SCC4 | CICR_SCC_SCC3 | CICR_SCB_SCC2 | CICR_SCA_SCC1) |
  135. ((hwirq/2) << 13) | CICR_HP_MASK);
  136. out_be32(&cpic_reg->cpic_cimr, 0);
  137. cpm_pic_host = irq_alloc_host(of_node_get(np), IRQ_HOST_MAP_LINEAR,
  138. 64, &cpm_pic_host_ops, 64);
  139. if (cpm_pic_host == NULL) {
  140. printk(KERN_ERR "CPM2 PIC: failed to allocate irq host!\n");
  141. sirq = NO_IRQ;
  142. goto end;
  143. }
  144. /* Install our own error handler. */
  145. np = of_find_compatible_node(NULL, NULL, "fsl,cpm1");
  146. if (np == NULL)
  147. np = of_find_node_by_type(NULL, "cpm");
  148. if (np == NULL) {
  149. printk(KERN_ERR "CPM PIC init: can not find cpm node\n");
  150. goto end;
  151. }
  152. eirq = irq_of_parse_and_map(np, 0);
  153. if (eirq == NO_IRQ)
  154. goto end;
  155. if (setup_irq(eirq, &cpm_error_irqaction))
  156. printk(KERN_ERR "Could not allocate CPM error IRQ!");
  157. setbits32(&cpic_reg->cpic_cicr, CICR_IEN);
  158. end:
  159. of_node_put(np);
  160. return sirq;
  161. }
  162. void __init cpm_reset(void)
  163. {
  164. sysconf8xx_t __iomem *siu_conf;
  165. mpc8xx_immr = ioremap(get_immrbase(), 0x4000);
  166. if (!mpc8xx_immr) {
  167. printk(KERN_CRIT "Could not map IMMR\n");
  168. return;
  169. }
  170. cpmp = &mpc8xx_immr->im_cpm;
  171. #ifndef CONFIG_PPC_EARLY_DEBUG_CPM
  172. /* Perform a reset.
  173. */
  174. out_be16(&cpmp->cp_cpcr, CPM_CR_RST | CPM_CR_FLG);
  175. /* Wait for it.
  176. */
  177. while (in_be16(&cpmp->cp_cpcr) & CPM_CR_FLG);
  178. #endif
  179. #ifdef CONFIG_UCODE_PATCH
  180. cpm_load_patch(cpmp);
  181. #endif
  182. /* Set SDMA Bus Request priority 5.
  183. * On 860T, this also enables FEC priority 6. I am not sure
  184. * this is what we realy want for some applications, but the
  185. * manual recommends it.
  186. * Bit 25, FAM can also be set to use FEC aggressive mode (860T).
  187. */
  188. siu_conf = immr_map(im_siu_conf);
  189. out_be32(&siu_conf->sc_sdcr, 1);
  190. immr_unmap(siu_conf);
  191. #ifdef CONFIG_PPC_CPM_NEW_BINDING
  192. cpm_muram_init();
  193. #else
  194. /* Reclaim the DP memory for our use. */
  195. m8xx_cpm_dpinit();
  196. #endif
  197. }
  198. static DEFINE_SPINLOCK(cmd_lock);
  199. #define MAX_CR_CMD_LOOPS 10000
  200. int cpm_command(u32 command, u8 opcode)
  201. {
  202. int i, ret;
  203. unsigned long flags;
  204. if (command & 0xffffff0f)
  205. return -EINVAL;
  206. spin_lock_irqsave(&cmd_lock, flags);
  207. ret = 0;
  208. out_be16(&cpmp->cp_cpcr, command | CPM_CR_FLG | (opcode << 8));
  209. for (i = 0; i < MAX_CR_CMD_LOOPS; i++)
  210. if ((in_be16(&cpmp->cp_cpcr) & CPM_CR_FLG) == 0)
  211. goto out;
  212. printk(KERN_ERR "%s(): Not able to issue CPM command\n", __FUNCTION__);
  213. ret = -EIO;
  214. out:
  215. spin_unlock_irqrestore(&cmd_lock, flags);
  216. return ret;
  217. }
  218. EXPORT_SYMBOL(cpm_command);
  219. /* Set a baud rate generator. This needs lots of work. There are
  220. * four BRGs, any of which can be wired to any channel.
  221. * The internal baud rate clock is the system clock divided by 16.
  222. * This assumes the baudrate is 16x oversampled by the uart.
  223. */
  224. #define BRG_INT_CLK (get_brgfreq())
  225. #define BRG_UART_CLK (BRG_INT_CLK/16)
  226. #define BRG_UART_CLK_DIV16 (BRG_UART_CLK/16)
  227. void
  228. cpm_setbrg(uint brg, uint rate)
  229. {
  230. u32 __iomem *bp;
  231. /* This is good enough to get SMCs running.....
  232. */
  233. bp = &cpmp->cp_brgc1;
  234. bp += brg;
  235. /* The BRG has a 12-bit counter. For really slow baud rates (or
  236. * really fast processors), we may have to further divide by 16.
  237. */
  238. if (((BRG_UART_CLK / rate) - 1) < 4096)
  239. out_be32(bp, (((BRG_UART_CLK / rate) - 1) << 1) | CPM_BRG_EN);
  240. else
  241. out_be32(bp, (((BRG_UART_CLK_DIV16 / rate) - 1) << 1) |
  242. CPM_BRG_EN | CPM_BRG_DIV16);
  243. }
  244. #ifndef CONFIG_PPC_CPM_NEW_BINDING
  245. /*
  246. * dpalloc / dpfree bits.
  247. */
  248. static spinlock_t cpm_dpmem_lock;
  249. /*
  250. * 16 blocks should be enough to satisfy all requests
  251. * until the memory subsystem goes up...
  252. */
  253. static rh_block_t cpm_boot_dpmem_rh_block[16];
  254. static rh_info_t cpm_dpmem_info;
  255. #define CPM_DPMEM_ALIGNMENT 8
  256. static u8 __iomem *dpram_vbase;
  257. static phys_addr_t dpram_pbase;
  258. static void m8xx_cpm_dpinit(void)
  259. {
  260. spin_lock_init(&cpm_dpmem_lock);
  261. dpram_vbase = cpmp->cp_dpmem;
  262. dpram_pbase = get_immrbase() + offsetof(immap_t, im_cpm.cp_dpmem);
  263. /* Initialize the info header */
  264. rh_init(&cpm_dpmem_info, CPM_DPMEM_ALIGNMENT,
  265. sizeof(cpm_boot_dpmem_rh_block) /
  266. sizeof(cpm_boot_dpmem_rh_block[0]),
  267. cpm_boot_dpmem_rh_block);
  268. /*
  269. * Attach the usable dpmem area.
  270. * XXX: This is actually crap. CPM_DATAONLY_BASE and
  271. * CPM_DATAONLY_SIZE are a subset of the available dparm. It varies
  272. * with the processor and the microcode patches applied / activated.
  273. * But the following should be at least safe.
  274. */
  275. rh_attach_region(&cpm_dpmem_info, CPM_DATAONLY_BASE, CPM_DATAONLY_SIZE);
  276. }
  277. /*
  278. * Allocate the requested size worth of DP memory.
  279. * This function returns an offset into the DPRAM area.
  280. * Use cpm_dpram_addr() to get the virtual address of the area.
  281. */
  282. unsigned long cpm_dpalloc(uint size, uint align)
  283. {
  284. unsigned long start;
  285. unsigned long flags;
  286. spin_lock_irqsave(&cpm_dpmem_lock, flags);
  287. cpm_dpmem_info.alignment = align;
  288. start = rh_alloc(&cpm_dpmem_info, size, "commproc");
  289. spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
  290. return (uint)start;
  291. }
  292. EXPORT_SYMBOL(cpm_dpalloc);
  293. int cpm_dpfree(unsigned long offset)
  294. {
  295. int ret;
  296. unsigned long flags;
  297. spin_lock_irqsave(&cpm_dpmem_lock, flags);
  298. ret = rh_free(&cpm_dpmem_info, offset);
  299. spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
  300. return ret;
  301. }
  302. EXPORT_SYMBOL(cpm_dpfree);
  303. unsigned long cpm_dpalloc_fixed(unsigned long offset, uint size, uint align)
  304. {
  305. unsigned long start;
  306. unsigned long flags;
  307. spin_lock_irqsave(&cpm_dpmem_lock, flags);
  308. cpm_dpmem_info.alignment = align;
  309. start = rh_alloc_fixed(&cpm_dpmem_info, offset, size, "commproc");
  310. spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
  311. return start;
  312. }
  313. EXPORT_SYMBOL(cpm_dpalloc_fixed);
  314. void cpm_dpdump(void)
  315. {
  316. rh_dump(&cpm_dpmem_info);
  317. }
  318. EXPORT_SYMBOL(cpm_dpdump);
  319. void *cpm_dpram_addr(unsigned long offset)
  320. {
  321. return (void *)(dpram_vbase + offset);
  322. }
  323. EXPORT_SYMBOL(cpm_dpram_addr);
  324. uint cpm_dpram_phys(u8 *addr)
  325. {
  326. return (dpram_pbase + (uint)(addr - dpram_vbase));
  327. }
  328. EXPORT_SYMBOL(cpm_dpram_phys);
  329. #endif /* !CONFIG_PPC_CPM_NEW_BINDING */
  330. struct cpm_ioport16 {
  331. __be16 dir, par, odr_sor, dat, intr;
  332. __be16 res[3];
  333. };
  334. struct cpm_ioport32 {
  335. __be32 dir, par, sor;
  336. };
  337. static void cpm1_set_pin32(int port, int pin, int flags)
  338. {
  339. struct cpm_ioport32 __iomem *iop;
  340. pin = 1 << (31 - pin);
  341. if (port == CPM_PORTB)
  342. iop = (struct cpm_ioport32 __iomem *)
  343. &mpc8xx_immr->im_cpm.cp_pbdir;
  344. else
  345. iop = (struct cpm_ioport32 __iomem *)
  346. &mpc8xx_immr->im_cpm.cp_pedir;
  347. if (flags & CPM_PIN_OUTPUT)
  348. setbits32(&iop->dir, pin);
  349. else
  350. clrbits32(&iop->dir, pin);
  351. if (!(flags & CPM_PIN_GPIO))
  352. setbits32(&iop->par, pin);
  353. else
  354. clrbits32(&iop->par, pin);
  355. if (port == CPM_PORTB) {
  356. if (flags & CPM_PIN_OPENDRAIN)
  357. setbits16(&mpc8xx_immr->im_cpm.cp_pbodr, pin);
  358. else
  359. clrbits16(&mpc8xx_immr->im_cpm.cp_pbodr, pin);
  360. }
  361. if (port == CPM_PORTE) {
  362. if (flags & CPM_PIN_SECONDARY)
  363. setbits32(&iop->sor, pin);
  364. else
  365. clrbits32(&iop->sor, pin);
  366. if (flags & CPM_PIN_OPENDRAIN)
  367. setbits32(&mpc8xx_immr->im_cpm.cp_peodr, pin);
  368. else
  369. clrbits32(&mpc8xx_immr->im_cpm.cp_peodr, pin);
  370. }
  371. }
  372. static void cpm1_set_pin16(int port, int pin, int flags)
  373. {
  374. struct cpm_ioport16 __iomem *iop =
  375. (struct cpm_ioport16 __iomem *)&mpc8xx_immr->im_ioport;
  376. pin = 1 << (15 - pin);
  377. if (port != 0)
  378. iop += port - 1;
  379. if (flags & CPM_PIN_OUTPUT)
  380. setbits16(&iop->dir, pin);
  381. else
  382. clrbits16(&iop->dir, pin);
  383. if (!(flags & CPM_PIN_GPIO))
  384. setbits16(&iop->par, pin);
  385. else
  386. clrbits16(&iop->par, pin);
  387. if (port == CPM_PORTA) {
  388. if (flags & CPM_PIN_OPENDRAIN)
  389. setbits16(&iop->odr_sor, pin);
  390. else
  391. clrbits16(&iop->odr_sor, pin);
  392. }
  393. if (port == CPM_PORTC) {
  394. if (flags & CPM_PIN_SECONDARY)
  395. setbits16(&iop->odr_sor, pin);
  396. else
  397. clrbits16(&iop->odr_sor, pin);
  398. }
  399. }
  400. void cpm1_set_pin(enum cpm_port port, int pin, int flags)
  401. {
  402. if (port == CPM_PORTB || port == CPM_PORTE)
  403. cpm1_set_pin32(port, pin, flags);
  404. else
  405. cpm1_set_pin16(port, pin, flags);
  406. }
  407. int cpm1_clk_setup(enum cpm_clk_target target, int clock, int mode)
  408. {
  409. int shift;
  410. int i, bits = 0;
  411. u32 __iomem *reg;
  412. u32 mask = 7;
  413. u8 clk_map[][3] = {
  414. {CPM_CLK_SCC1, CPM_BRG1, 0},
  415. {CPM_CLK_SCC1, CPM_BRG2, 1},
  416. {CPM_CLK_SCC1, CPM_BRG3, 2},
  417. {CPM_CLK_SCC1, CPM_BRG4, 3},
  418. {CPM_CLK_SCC1, CPM_CLK1, 4},
  419. {CPM_CLK_SCC1, CPM_CLK2, 5},
  420. {CPM_CLK_SCC1, CPM_CLK3, 6},
  421. {CPM_CLK_SCC1, CPM_CLK4, 7},
  422. {CPM_CLK_SCC2, CPM_BRG1, 0},
  423. {CPM_CLK_SCC2, CPM_BRG2, 1},
  424. {CPM_CLK_SCC2, CPM_BRG3, 2},
  425. {CPM_CLK_SCC2, CPM_BRG4, 3},
  426. {CPM_CLK_SCC2, CPM_CLK1, 4},
  427. {CPM_CLK_SCC2, CPM_CLK2, 5},
  428. {CPM_CLK_SCC2, CPM_CLK3, 6},
  429. {CPM_CLK_SCC2, CPM_CLK4, 7},
  430. {CPM_CLK_SCC3, CPM_BRG1, 0},
  431. {CPM_CLK_SCC3, CPM_BRG2, 1},
  432. {CPM_CLK_SCC3, CPM_BRG3, 2},
  433. {CPM_CLK_SCC3, CPM_BRG4, 3},
  434. {CPM_CLK_SCC3, CPM_CLK5, 4},
  435. {CPM_CLK_SCC3, CPM_CLK6, 5},
  436. {CPM_CLK_SCC3, CPM_CLK7, 6},
  437. {CPM_CLK_SCC3, CPM_CLK8, 7},
  438. {CPM_CLK_SCC4, CPM_BRG1, 0},
  439. {CPM_CLK_SCC4, CPM_BRG2, 1},
  440. {CPM_CLK_SCC4, CPM_BRG3, 2},
  441. {CPM_CLK_SCC4, CPM_BRG4, 3},
  442. {CPM_CLK_SCC4, CPM_CLK5, 4},
  443. {CPM_CLK_SCC4, CPM_CLK6, 5},
  444. {CPM_CLK_SCC4, CPM_CLK7, 6},
  445. {CPM_CLK_SCC4, CPM_CLK8, 7},
  446. {CPM_CLK_SMC1, CPM_BRG1, 0},
  447. {CPM_CLK_SMC1, CPM_BRG2, 1},
  448. {CPM_CLK_SMC1, CPM_BRG3, 2},
  449. {CPM_CLK_SMC1, CPM_BRG4, 3},
  450. {CPM_CLK_SMC1, CPM_CLK1, 4},
  451. {CPM_CLK_SMC1, CPM_CLK2, 5},
  452. {CPM_CLK_SMC1, CPM_CLK3, 6},
  453. {CPM_CLK_SMC1, CPM_CLK4, 7},
  454. {CPM_CLK_SMC2, CPM_BRG1, 0},
  455. {CPM_CLK_SMC2, CPM_BRG2, 1},
  456. {CPM_CLK_SMC2, CPM_BRG3, 2},
  457. {CPM_CLK_SMC2, CPM_BRG4, 3},
  458. {CPM_CLK_SMC2, CPM_CLK5, 4},
  459. {CPM_CLK_SMC2, CPM_CLK6, 5},
  460. {CPM_CLK_SMC2, CPM_CLK7, 6},
  461. {CPM_CLK_SMC2, CPM_CLK8, 7},
  462. };
  463. switch (target) {
  464. case CPM_CLK_SCC1:
  465. reg = &mpc8xx_immr->im_cpm.cp_sicr;
  466. shift = 0;
  467. break;
  468. case CPM_CLK_SCC2:
  469. reg = &mpc8xx_immr->im_cpm.cp_sicr;
  470. shift = 8;
  471. break;
  472. case CPM_CLK_SCC3:
  473. reg = &mpc8xx_immr->im_cpm.cp_sicr;
  474. shift = 16;
  475. break;
  476. case CPM_CLK_SCC4:
  477. reg = &mpc8xx_immr->im_cpm.cp_sicr;
  478. shift = 24;
  479. break;
  480. case CPM_CLK_SMC1:
  481. reg = &mpc8xx_immr->im_cpm.cp_simode;
  482. shift = 12;
  483. break;
  484. case CPM_CLK_SMC2:
  485. reg = &mpc8xx_immr->im_cpm.cp_simode;
  486. shift = 28;
  487. break;
  488. default:
  489. printk(KERN_ERR "cpm1_clock_setup: invalid clock target\n");
  490. return -EINVAL;
  491. }
  492. if (reg == &mpc8xx_immr->im_cpm.cp_sicr && mode == CPM_CLK_RX)
  493. shift += 3;
  494. for (i = 0; i < ARRAY_SIZE(clk_map); i++) {
  495. if (clk_map[i][0] == target && clk_map[i][1] == clock) {
  496. bits = clk_map[i][2];
  497. break;
  498. }
  499. }
  500. if (i == ARRAY_SIZE(clk_map)) {
  501. printk(KERN_ERR "cpm1_clock_setup: invalid clock combination\n");
  502. return -EINVAL;
  503. }
  504. bits <<= shift;
  505. mask <<= shift;
  506. out_be32(reg, (in_be32(reg) & ~mask) | bits);
  507. return 0;
  508. }