vlynq.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815
  1. /*
  2. * Copyright (C) 2006, 2007 Eugene Konev <ejka@openwrt.org>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  17. *
  18. * Parts of the VLYNQ specification can be found here:
  19. * http://www.ti.com/litv/pdf/sprue36a
  20. */
  21. #include <linux/init.h>
  22. #include <linux/types.h>
  23. #include <linux/kernel.h>
  24. #include <linux/string.h>
  25. #include <linux/device.h>
  26. #include <linux/module.h>
  27. #include <linux/errno.h>
  28. #include <linux/platform_device.h>
  29. #include <linux/interrupt.h>
  30. #include <linux/delay.h>
  31. #include <linux/io.h>
  32. #include <linux/slab.h>
  33. #include <linux/irq.h>
  34. #include <linux/vlynq.h>
  35. #define VLYNQ_CTRL_PM_ENABLE 0x80000000
  36. #define VLYNQ_CTRL_CLOCK_INT 0x00008000
  37. #define VLYNQ_CTRL_CLOCK_DIV(x) (((x) & 7) << 16)
  38. #define VLYNQ_CTRL_INT_LOCAL 0x00004000
  39. #define VLYNQ_CTRL_INT_ENABLE 0x00002000
  40. #define VLYNQ_CTRL_INT_VECTOR(x) (((x) & 0x1f) << 8)
  41. #define VLYNQ_CTRL_INT2CFG 0x00000080
  42. #define VLYNQ_CTRL_RESET 0x00000001
  43. #define VLYNQ_CTRL_CLOCK_MASK (0x7 << 16)
  44. #define VLYNQ_INT_OFFSET 0x00000014
  45. #define VLYNQ_REMOTE_OFFSET 0x00000080
  46. #define VLYNQ_STATUS_LINK 0x00000001
  47. #define VLYNQ_STATUS_LERROR 0x00000080
  48. #define VLYNQ_STATUS_RERROR 0x00000100
  49. #define VINT_ENABLE 0x00000100
  50. #define VINT_TYPE_EDGE 0x00000080
  51. #define VINT_LEVEL_LOW 0x00000040
  52. #define VINT_VECTOR(x) ((x) & 0x1f)
  53. #define VINT_OFFSET(irq) (8 * ((irq) % 4))
  54. #define VLYNQ_AUTONEGO_V2 0x00010000
  55. struct vlynq_regs {
  56. u32 revision;
  57. u32 control;
  58. u32 status;
  59. u32 int_prio;
  60. u32 int_status;
  61. u32 int_pending;
  62. u32 int_ptr;
  63. u32 tx_offset;
  64. struct vlynq_mapping rx_mapping[4];
  65. u32 chip;
  66. u32 autonego;
  67. u32 unused[6];
  68. u32 int_device[8];
  69. };
  70. #ifdef CONFIG_VLYNQ_DEBUG
  71. static void vlynq_dump_regs(struct vlynq_device *dev)
  72. {
  73. int i;
  74. printk(KERN_DEBUG "VLYNQ local=%p remote=%p\n",
  75. dev->local, dev->remote);
  76. for (i = 0; i < 32; i++) {
  77. printk(KERN_DEBUG "VLYNQ: local %d: %08x\n",
  78. i + 1, ((u32 *)dev->local)[i]);
  79. printk(KERN_DEBUG "VLYNQ: remote %d: %08x\n",
  80. i + 1, ((u32 *)dev->remote)[i]);
  81. }
  82. }
  83. static void vlynq_dump_mem(u32 *base, int count)
  84. {
  85. int i;
  86. for (i = 0; i < (count + 3) / 4; i++) {
  87. if (i % 4 == 0)
  88. printk(KERN_DEBUG "\nMEM[0x%04x]:", i * 4);
  89. printk(KERN_DEBUG " 0x%08x", *(base + i));
  90. }
  91. printk(KERN_DEBUG "\n");
  92. }
  93. #endif
  94. /* Check the VLYNQ link status with a given device */
  95. static int vlynq_linked(struct vlynq_device *dev)
  96. {
  97. int i;
  98. for (i = 0; i < 100; i++)
  99. if (readl(&dev->local->status) & VLYNQ_STATUS_LINK)
  100. return 1;
  101. else
  102. cpu_relax();
  103. return 0;
  104. }
  105. static void vlynq_reset(struct vlynq_device *dev)
  106. {
  107. writel(readl(&dev->local->control) | VLYNQ_CTRL_RESET,
  108. &dev->local->control);
  109. /* Wait for the devices to finish resetting */
  110. msleep(5);
  111. /* Remove reset bit */
  112. writel(readl(&dev->local->control) & ~VLYNQ_CTRL_RESET,
  113. &dev->local->control);
  114. /* Give some time for the devices to settle */
  115. msleep(5);
  116. }
  117. static void vlynq_irq_unmask(struct irq_data *d)
  118. {
  119. struct vlynq_device *dev = irq_data_get_irq_chip_data(d);
  120. int virq;
  121. u32 val;
  122. BUG_ON(!dev);
  123. virq = d->irq - dev->irq_start;
  124. val = readl(&dev->remote->int_device[virq >> 2]);
  125. val |= (VINT_ENABLE | virq) << VINT_OFFSET(virq);
  126. writel(val, &dev->remote->int_device[virq >> 2]);
  127. }
  128. static void vlynq_irq_mask(struct irq_data *d)
  129. {
  130. struct vlynq_device *dev = irq_data_get_irq_chip_data(d);
  131. int virq;
  132. u32 val;
  133. BUG_ON(!dev);
  134. virq = d->irq - dev->irq_start;
  135. val = readl(&dev->remote->int_device[virq >> 2]);
  136. val &= ~(VINT_ENABLE << VINT_OFFSET(virq));
  137. writel(val, &dev->remote->int_device[virq >> 2]);
  138. }
  139. static int vlynq_irq_type(struct irq_data *d, unsigned int flow_type)
  140. {
  141. struct vlynq_device *dev = irq_data_get_irq_chip_data(d);
  142. int virq;
  143. u32 val;
  144. BUG_ON(!dev);
  145. virq = d->irq - dev->irq_start;
  146. val = readl(&dev->remote->int_device[virq >> 2]);
  147. switch (flow_type & IRQ_TYPE_SENSE_MASK) {
  148. case IRQ_TYPE_EDGE_RISING:
  149. case IRQ_TYPE_EDGE_FALLING:
  150. case IRQ_TYPE_EDGE_BOTH:
  151. val |= VINT_TYPE_EDGE << VINT_OFFSET(virq);
  152. val &= ~(VINT_LEVEL_LOW << VINT_OFFSET(virq));
  153. break;
  154. case IRQ_TYPE_LEVEL_HIGH:
  155. val &= ~(VINT_TYPE_EDGE << VINT_OFFSET(virq));
  156. val &= ~(VINT_LEVEL_LOW << VINT_OFFSET(virq));
  157. break;
  158. case IRQ_TYPE_LEVEL_LOW:
  159. val &= ~(VINT_TYPE_EDGE << VINT_OFFSET(virq));
  160. val |= VINT_LEVEL_LOW << VINT_OFFSET(virq);
  161. break;
  162. default:
  163. return -EINVAL;
  164. }
  165. writel(val, &dev->remote->int_device[virq >> 2]);
  166. return 0;
  167. }
  168. static void vlynq_local_ack(struct irq_data *d)
  169. {
  170. struct vlynq_device *dev = irq_data_get_irq_chip_data(d);
  171. u32 status = readl(&dev->local->status);
  172. pr_debug("%s: local status: 0x%08x\n",
  173. dev_name(&dev->dev), status);
  174. writel(status, &dev->local->status);
  175. }
  176. static void vlynq_remote_ack(struct irq_data *d)
  177. {
  178. struct vlynq_device *dev = irq_data_get_irq_chip_data(d);
  179. u32 status = readl(&dev->remote->status);
  180. pr_debug("%s: remote status: 0x%08x\n",
  181. dev_name(&dev->dev), status);
  182. writel(status, &dev->remote->status);
  183. }
  184. static irqreturn_t vlynq_irq(int irq, void *dev_id)
  185. {
  186. struct vlynq_device *dev = dev_id;
  187. u32 status;
  188. int virq = 0;
  189. status = readl(&dev->local->int_status);
  190. writel(status, &dev->local->int_status);
  191. if (unlikely(!status))
  192. spurious_interrupt();
  193. while (status) {
  194. if (status & 1)
  195. do_IRQ(dev->irq_start + virq);
  196. status >>= 1;
  197. virq++;
  198. }
  199. return IRQ_HANDLED;
  200. }
  201. static struct irq_chip vlynq_irq_chip = {
  202. .name = "vlynq",
  203. .irq_unmask = vlynq_irq_unmask,
  204. .irq_mask = vlynq_irq_mask,
  205. .irq_set_type = vlynq_irq_type,
  206. };
  207. static struct irq_chip vlynq_local_chip = {
  208. .name = "vlynq local error",
  209. .irq_unmask = vlynq_irq_unmask,
  210. .irq_mask = vlynq_irq_mask,
  211. .irq_ack = vlynq_local_ack,
  212. };
  213. static struct irq_chip vlynq_remote_chip = {
  214. .name = "vlynq local error",
  215. .irq_unmask = vlynq_irq_unmask,
  216. .irq_mask = vlynq_irq_mask,
  217. .irq_ack = vlynq_remote_ack,
  218. };
  219. static int vlynq_setup_irq(struct vlynq_device *dev)
  220. {
  221. u32 val;
  222. int i, virq;
  223. if (dev->local_irq == dev->remote_irq) {
  224. printk(KERN_ERR
  225. "%s: local vlynq irq should be different from remote\n",
  226. dev_name(&dev->dev));
  227. return -EINVAL;
  228. }
  229. /* Clear local and remote error bits */
  230. writel(readl(&dev->local->status), &dev->local->status);
  231. writel(readl(&dev->remote->status), &dev->remote->status);
  232. /* Now setup interrupts */
  233. val = VLYNQ_CTRL_INT_VECTOR(dev->local_irq);
  234. val |= VLYNQ_CTRL_INT_ENABLE | VLYNQ_CTRL_INT_LOCAL |
  235. VLYNQ_CTRL_INT2CFG;
  236. val |= readl(&dev->local->control);
  237. writel(VLYNQ_INT_OFFSET, &dev->local->int_ptr);
  238. writel(val, &dev->local->control);
  239. val = VLYNQ_CTRL_INT_VECTOR(dev->remote_irq);
  240. val |= VLYNQ_CTRL_INT_ENABLE;
  241. val |= readl(&dev->remote->control);
  242. writel(VLYNQ_INT_OFFSET, &dev->remote->int_ptr);
  243. writel(val, &dev->remote->int_ptr);
  244. writel(val, &dev->remote->control);
  245. for (i = dev->irq_start; i <= dev->irq_end; i++) {
  246. virq = i - dev->irq_start;
  247. if (virq == dev->local_irq) {
  248. irq_set_chip_and_handler(i, &vlynq_local_chip,
  249. handle_level_irq);
  250. irq_set_chip_data(i, dev);
  251. } else if (virq == dev->remote_irq) {
  252. irq_set_chip_and_handler(i, &vlynq_remote_chip,
  253. handle_level_irq);
  254. irq_set_chip_data(i, dev);
  255. } else {
  256. irq_set_chip_and_handler(i, &vlynq_irq_chip,
  257. handle_simple_irq);
  258. irq_set_chip_data(i, dev);
  259. writel(0, &dev->remote->int_device[virq >> 2]);
  260. }
  261. }
  262. if (request_irq(dev->irq, vlynq_irq, IRQF_SHARED, "vlynq", dev)) {
  263. printk(KERN_ERR "%s: request_irq failed\n",
  264. dev_name(&dev->dev));
  265. return -EAGAIN;
  266. }
  267. return 0;
  268. }
  269. static void vlynq_device_release(struct device *dev)
  270. {
  271. struct vlynq_device *vdev = to_vlynq_device(dev);
  272. kfree(vdev);
  273. }
  274. static int vlynq_device_match(struct device *dev,
  275. struct device_driver *drv)
  276. {
  277. struct vlynq_device *vdev = to_vlynq_device(dev);
  278. struct vlynq_driver *vdrv = to_vlynq_driver(drv);
  279. struct vlynq_device_id *ids = vdrv->id_table;
  280. while (ids->id) {
  281. if (ids->id == vdev->dev_id) {
  282. vdev->divisor = ids->divisor;
  283. vlynq_set_drvdata(vdev, ids);
  284. printk(KERN_INFO "Driver found for VLYNQ "
  285. "device: %08x\n", vdev->dev_id);
  286. return 1;
  287. }
  288. printk(KERN_DEBUG "Not using the %08x VLYNQ device's driver"
  289. " for VLYNQ device: %08x\n", ids->id, vdev->dev_id);
  290. ids++;
  291. }
  292. return 0;
  293. }
  294. static int vlynq_device_probe(struct device *dev)
  295. {
  296. struct vlynq_device *vdev = to_vlynq_device(dev);
  297. struct vlynq_driver *drv = to_vlynq_driver(dev->driver);
  298. struct vlynq_device_id *id = vlynq_get_drvdata(vdev);
  299. int result = -ENODEV;
  300. if (drv->probe)
  301. result = drv->probe(vdev, id);
  302. if (result)
  303. put_device(dev);
  304. return result;
  305. }
  306. static int vlynq_device_remove(struct device *dev)
  307. {
  308. struct vlynq_driver *drv = to_vlynq_driver(dev->driver);
  309. if (drv->remove)
  310. drv->remove(to_vlynq_device(dev));
  311. return 0;
  312. }
  313. int __vlynq_register_driver(struct vlynq_driver *driver, struct module *owner)
  314. {
  315. driver->driver.name = driver->name;
  316. driver->driver.bus = &vlynq_bus_type;
  317. return driver_register(&driver->driver);
  318. }
  319. EXPORT_SYMBOL(__vlynq_register_driver);
  320. void vlynq_unregister_driver(struct vlynq_driver *driver)
  321. {
  322. driver_unregister(&driver->driver);
  323. }
  324. EXPORT_SYMBOL(vlynq_unregister_driver);
  325. /*
  326. * A VLYNQ remote device can clock the VLYNQ bus master
  327. * using a dedicated clock line. In that case, both the
  328. * remove device and the bus master should have the same
  329. * serial clock dividers configured. Iterate through the
  330. * 8 possible dividers until we actually link with the
  331. * device.
  332. */
  333. static int __vlynq_try_remote(struct vlynq_device *dev)
  334. {
  335. int i;
  336. vlynq_reset(dev);
  337. for (i = dev->dev_id ? vlynq_rdiv2 : vlynq_rdiv8; dev->dev_id ?
  338. i <= vlynq_rdiv8 : i >= vlynq_rdiv2;
  339. dev->dev_id ? i++ : i--) {
  340. if (!vlynq_linked(dev))
  341. break;
  342. writel((readl(&dev->remote->control) &
  343. ~VLYNQ_CTRL_CLOCK_MASK) |
  344. VLYNQ_CTRL_CLOCK_INT |
  345. VLYNQ_CTRL_CLOCK_DIV(i - vlynq_rdiv1),
  346. &dev->remote->control);
  347. writel((readl(&dev->local->control)
  348. & ~(VLYNQ_CTRL_CLOCK_INT |
  349. VLYNQ_CTRL_CLOCK_MASK)) |
  350. VLYNQ_CTRL_CLOCK_DIV(i - vlynq_rdiv1),
  351. &dev->local->control);
  352. if (vlynq_linked(dev)) {
  353. printk(KERN_DEBUG
  354. "%s: using remote clock divisor %d\n",
  355. dev_name(&dev->dev), i - vlynq_rdiv1 + 1);
  356. dev->divisor = i;
  357. return 0;
  358. } else {
  359. vlynq_reset(dev);
  360. }
  361. }
  362. return -ENODEV;
  363. }
  364. /*
  365. * A VLYNQ remote device can be clocked by the VLYNQ bus
  366. * master using a dedicated clock line. In that case, only
  367. * the bus master configures the serial clock divider.
  368. * Iterate through the 8 possible dividers until we
  369. * actually get a link with the device.
  370. */
  371. static int __vlynq_try_local(struct vlynq_device *dev)
  372. {
  373. int i;
  374. vlynq_reset(dev);
  375. for (i = dev->dev_id ? vlynq_ldiv2 : vlynq_ldiv8; dev->dev_id ?
  376. i <= vlynq_ldiv8 : i >= vlynq_ldiv2;
  377. dev->dev_id ? i++ : i--) {
  378. writel((readl(&dev->local->control) &
  379. ~VLYNQ_CTRL_CLOCK_MASK) |
  380. VLYNQ_CTRL_CLOCK_INT |
  381. VLYNQ_CTRL_CLOCK_DIV(i - vlynq_ldiv1),
  382. &dev->local->control);
  383. if (vlynq_linked(dev)) {
  384. printk(KERN_DEBUG
  385. "%s: using local clock divisor %d\n",
  386. dev_name(&dev->dev), i - vlynq_ldiv1 + 1);
  387. dev->divisor = i;
  388. return 0;
  389. } else {
  390. vlynq_reset(dev);
  391. }
  392. }
  393. return -ENODEV;
  394. }
  395. /*
  396. * When using external clocking method, serial clock
  397. * is supplied by an external oscillator, therefore we
  398. * should mask the local clock bit in the clock control
  399. * register for both the bus master and the remote device.
  400. */
  401. static int __vlynq_try_external(struct vlynq_device *dev)
  402. {
  403. vlynq_reset(dev);
  404. if (!vlynq_linked(dev))
  405. return -ENODEV;
  406. writel((readl(&dev->remote->control) &
  407. ~VLYNQ_CTRL_CLOCK_INT),
  408. &dev->remote->control);
  409. writel((readl(&dev->local->control) &
  410. ~VLYNQ_CTRL_CLOCK_INT),
  411. &dev->local->control);
  412. if (vlynq_linked(dev)) {
  413. printk(KERN_DEBUG "%s: using external clock\n",
  414. dev_name(&dev->dev));
  415. dev->divisor = vlynq_div_external;
  416. return 0;
  417. }
  418. return -ENODEV;
  419. }
  420. static int __vlynq_enable_device(struct vlynq_device *dev)
  421. {
  422. int result;
  423. struct plat_vlynq_ops *ops = dev->dev.platform_data;
  424. result = ops->on(dev);
  425. if (result)
  426. return result;
  427. switch (dev->divisor) {
  428. case vlynq_div_external:
  429. case vlynq_div_auto:
  430. /* When the device is brought from reset it should have clock
  431. * generation negotiated by hardware.
  432. * Check which device is generating clocks and perform setup
  433. * accordingly */
  434. if (vlynq_linked(dev) && readl(&dev->remote->control) &
  435. VLYNQ_CTRL_CLOCK_INT) {
  436. if (!__vlynq_try_remote(dev) ||
  437. !__vlynq_try_local(dev) ||
  438. !__vlynq_try_external(dev))
  439. return 0;
  440. } else {
  441. if (!__vlynq_try_external(dev) ||
  442. !__vlynq_try_local(dev) ||
  443. !__vlynq_try_remote(dev))
  444. return 0;
  445. }
  446. break;
  447. case vlynq_ldiv1:
  448. case vlynq_ldiv2:
  449. case vlynq_ldiv3:
  450. case vlynq_ldiv4:
  451. case vlynq_ldiv5:
  452. case vlynq_ldiv6:
  453. case vlynq_ldiv7:
  454. case vlynq_ldiv8:
  455. writel(VLYNQ_CTRL_CLOCK_INT |
  456. VLYNQ_CTRL_CLOCK_DIV(dev->divisor -
  457. vlynq_ldiv1), &dev->local->control);
  458. writel(0, &dev->remote->control);
  459. if (vlynq_linked(dev)) {
  460. printk(KERN_DEBUG
  461. "%s: using local clock divisor %d\n",
  462. dev_name(&dev->dev),
  463. dev->divisor - vlynq_ldiv1 + 1);
  464. return 0;
  465. }
  466. break;
  467. case vlynq_rdiv1:
  468. case vlynq_rdiv2:
  469. case vlynq_rdiv3:
  470. case vlynq_rdiv4:
  471. case vlynq_rdiv5:
  472. case vlynq_rdiv6:
  473. case vlynq_rdiv7:
  474. case vlynq_rdiv8:
  475. writel(0, &dev->local->control);
  476. writel(VLYNQ_CTRL_CLOCK_INT |
  477. VLYNQ_CTRL_CLOCK_DIV(dev->divisor -
  478. vlynq_rdiv1), &dev->remote->control);
  479. if (vlynq_linked(dev)) {
  480. printk(KERN_DEBUG
  481. "%s: using remote clock divisor %d\n",
  482. dev_name(&dev->dev),
  483. dev->divisor - vlynq_rdiv1 + 1);
  484. return 0;
  485. }
  486. break;
  487. }
  488. ops->off(dev);
  489. return -ENODEV;
  490. }
  491. int vlynq_enable_device(struct vlynq_device *dev)
  492. {
  493. struct plat_vlynq_ops *ops = dev->dev.platform_data;
  494. int result = -ENODEV;
  495. result = __vlynq_enable_device(dev);
  496. if (result)
  497. return result;
  498. result = vlynq_setup_irq(dev);
  499. if (result)
  500. ops->off(dev);
  501. dev->enabled = !result;
  502. return result;
  503. }
  504. EXPORT_SYMBOL(vlynq_enable_device);
  505. void vlynq_disable_device(struct vlynq_device *dev)
  506. {
  507. struct plat_vlynq_ops *ops = dev->dev.platform_data;
  508. dev->enabled = 0;
  509. free_irq(dev->irq, dev);
  510. ops->off(dev);
  511. }
  512. EXPORT_SYMBOL(vlynq_disable_device);
  513. int vlynq_set_local_mapping(struct vlynq_device *dev, u32 tx_offset,
  514. struct vlynq_mapping *mapping)
  515. {
  516. int i;
  517. if (!dev->enabled)
  518. return -ENXIO;
  519. writel(tx_offset, &dev->local->tx_offset);
  520. for (i = 0; i < 4; i++) {
  521. writel(mapping[i].offset, &dev->local->rx_mapping[i].offset);
  522. writel(mapping[i].size, &dev->local->rx_mapping[i].size);
  523. }
  524. return 0;
  525. }
  526. EXPORT_SYMBOL(vlynq_set_local_mapping);
  527. int vlynq_set_remote_mapping(struct vlynq_device *dev, u32 tx_offset,
  528. struct vlynq_mapping *mapping)
  529. {
  530. int i;
  531. if (!dev->enabled)
  532. return -ENXIO;
  533. writel(tx_offset, &dev->remote->tx_offset);
  534. for (i = 0; i < 4; i++) {
  535. writel(mapping[i].offset, &dev->remote->rx_mapping[i].offset);
  536. writel(mapping[i].size, &dev->remote->rx_mapping[i].size);
  537. }
  538. return 0;
  539. }
  540. EXPORT_SYMBOL(vlynq_set_remote_mapping);
  541. int vlynq_set_local_irq(struct vlynq_device *dev, int virq)
  542. {
  543. int irq = dev->irq_start + virq;
  544. if (dev->enabled)
  545. return -EBUSY;
  546. if ((irq < dev->irq_start) || (irq > dev->irq_end))
  547. return -EINVAL;
  548. if (virq == dev->remote_irq)
  549. return -EINVAL;
  550. dev->local_irq = virq;
  551. return 0;
  552. }
  553. EXPORT_SYMBOL(vlynq_set_local_irq);
  554. int vlynq_set_remote_irq(struct vlynq_device *dev, int virq)
  555. {
  556. int irq = dev->irq_start + virq;
  557. if (dev->enabled)
  558. return -EBUSY;
  559. if ((irq < dev->irq_start) || (irq > dev->irq_end))
  560. return -EINVAL;
  561. if (virq == dev->local_irq)
  562. return -EINVAL;
  563. dev->remote_irq = virq;
  564. return 0;
  565. }
  566. EXPORT_SYMBOL(vlynq_set_remote_irq);
  567. static int vlynq_probe(struct platform_device *pdev)
  568. {
  569. struct vlynq_device *dev;
  570. struct resource *regs_res, *mem_res, *irq_res;
  571. int len, result;
  572. regs_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
  573. if (!regs_res)
  574. return -ENODEV;
  575. mem_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem");
  576. if (!mem_res)
  577. return -ENODEV;
  578. irq_res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "devirq");
  579. if (!irq_res)
  580. return -ENODEV;
  581. dev = kzalloc(sizeof(*dev), GFP_KERNEL);
  582. if (!dev) {
  583. printk(KERN_ERR
  584. "vlynq: failed to allocate device structure\n");
  585. return -ENOMEM;
  586. }
  587. dev->id = pdev->id;
  588. dev->dev.bus = &vlynq_bus_type;
  589. dev->dev.parent = &pdev->dev;
  590. dev_set_name(&dev->dev, "vlynq%d", dev->id);
  591. dev->dev.platform_data = pdev->dev.platform_data;
  592. dev->dev.release = vlynq_device_release;
  593. dev->regs_start = regs_res->start;
  594. dev->regs_end = regs_res->end;
  595. dev->mem_start = mem_res->start;
  596. dev->mem_end = mem_res->end;
  597. len = resource_size(regs_res);
  598. if (!request_mem_region(regs_res->start, len, dev_name(&dev->dev))) {
  599. printk(KERN_ERR "%s: Can't request vlynq registers\n",
  600. dev_name(&dev->dev));
  601. result = -ENXIO;
  602. goto fail_request;
  603. }
  604. dev->local = ioremap(regs_res->start, len);
  605. if (!dev->local) {
  606. printk(KERN_ERR "%s: Can't remap vlynq registers\n",
  607. dev_name(&dev->dev));
  608. result = -ENXIO;
  609. goto fail_remap;
  610. }
  611. dev->remote = (struct vlynq_regs *)((void *)dev->local +
  612. VLYNQ_REMOTE_OFFSET);
  613. dev->irq = platform_get_irq_byname(pdev, "irq");
  614. dev->irq_start = irq_res->start;
  615. dev->irq_end = irq_res->end;
  616. dev->local_irq = dev->irq_end - dev->irq_start;
  617. dev->remote_irq = dev->local_irq - 1;
  618. if (device_register(&dev->dev))
  619. goto fail_register;
  620. platform_set_drvdata(pdev, dev);
  621. printk(KERN_INFO "%s: regs 0x%p, irq %d, mem 0x%p\n",
  622. dev_name(&dev->dev), (void *)dev->regs_start, dev->irq,
  623. (void *)dev->mem_start);
  624. dev->dev_id = 0;
  625. dev->divisor = vlynq_div_auto;
  626. result = __vlynq_enable_device(dev);
  627. if (result == 0) {
  628. dev->dev_id = readl(&dev->remote->chip);
  629. ((struct plat_vlynq_ops *)(dev->dev.platform_data))->off(dev);
  630. }
  631. if (dev->dev_id)
  632. printk(KERN_INFO "Found a VLYNQ device: %08x\n", dev->dev_id);
  633. return 0;
  634. fail_register:
  635. iounmap(dev->local);
  636. fail_remap:
  637. fail_request:
  638. release_mem_region(regs_res->start, len);
  639. kfree(dev);
  640. return result;
  641. }
  642. static int vlynq_remove(struct platform_device *pdev)
  643. {
  644. struct vlynq_device *dev = platform_get_drvdata(pdev);
  645. device_unregister(&dev->dev);
  646. iounmap(dev->local);
  647. release_mem_region(dev->regs_start,
  648. dev->regs_end - dev->regs_start + 1);
  649. kfree(dev);
  650. return 0;
  651. }
  652. static struct platform_driver vlynq_platform_driver = {
  653. .driver.name = "vlynq",
  654. .probe = vlynq_probe,
  655. .remove = vlynq_remove,
  656. };
  657. struct bus_type vlynq_bus_type = {
  658. .name = "vlynq",
  659. .match = vlynq_device_match,
  660. .probe = vlynq_device_probe,
  661. .remove = vlynq_device_remove,
  662. };
  663. EXPORT_SYMBOL(vlynq_bus_type);
  664. static int vlynq_init(void)
  665. {
  666. int res = 0;
  667. res = bus_register(&vlynq_bus_type);
  668. if (res)
  669. goto fail_bus;
  670. res = platform_driver_register(&vlynq_platform_driver);
  671. if (res)
  672. goto fail_platform;
  673. return 0;
  674. fail_platform:
  675. bus_unregister(&vlynq_bus_type);
  676. fail_bus:
  677. return res;
  678. }
  679. static void vlynq_exit(void)
  680. {
  681. platform_driver_unregister(&vlynq_platform_driver);
  682. bus_unregister(&vlynq_bus_type);
  683. }
  684. module_init(vlynq_init);
  685. module_exit(vlynq_exit);