samsung-usbphy.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928
  1. /* linux/drivers/usb/phy/samsung-usbphy.c
  2. *
  3. * Copyright (c) 2012 Samsung Electronics Co., Ltd.
  4. * http://www.samsung.com
  5. *
  6. * Author: Praveen Paneri <p.paneri@samsung.com>
  7. *
  8. * Samsung USB2.0 PHY transceiver; talks to S3C HS OTG controller, EHCI-S5P and
  9. * OHCI-EXYNOS controllers.
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License version 2 as
  13. * published by the Free Software Foundation.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. */
  20. #include <linux/module.h>
  21. #include <linux/platform_device.h>
  22. #include <linux/clk.h>
  23. #include <linux/delay.h>
  24. #include <linux/device.h>
  25. #include <linux/err.h>
  26. #include <linux/io.h>
  27. #include <linux/of.h>
  28. #include <linux/of_address.h>
  29. #include <linux/usb/otg.h>
  30. #include <linux/usb/samsung_usb_phy.h>
  31. #include <linux/platform_data/samsung-usbphy.h>
  32. /* Register definitions */
  33. #define SAMSUNG_PHYPWR (0x00)
  34. #define PHYPWR_NORMAL_MASK (0x19 << 0)
  35. #define PHYPWR_OTG_DISABLE (0x1 << 4)
  36. #define PHYPWR_ANALOG_POWERDOWN (0x1 << 3)
  37. #define PHYPWR_FORCE_SUSPEND (0x1 << 1)
  38. /* For Exynos4 */
  39. #define PHYPWR_NORMAL_MASK_PHY0 (0x39 << 0)
  40. #define PHYPWR_SLEEP_PHY0 (0x1 << 5)
  41. #define SAMSUNG_PHYCLK (0x04)
  42. #define PHYCLK_MODE_USB11 (0x1 << 6)
  43. #define PHYCLK_EXT_OSC (0x1 << 5)
  44. #define PHYCLK_COMMON_ON_N (0x1 << 4)
  45. #define PHYCLK_ID_PULL (0x1 << 2)
  46. #define PHYCLK_CLKSEL_MASK (0x3 << 0)
  47. #define PHYCLK_CLKSEL_48M (0x0 << 0)
  48. #define PHYCLK_CLKSEL_12M (0x2 << 0)
  49. #define PHYCLK_CLKSEL_24M (0x3 << 0)
  50. #define SAMSUNG_RSTCON (0x08)
  51. #define RSTCON_PHYLINK_SWRST (0x1 << 2)
  52. #define RSTCON_HLINK_SWRST (0x1 << 1)
  53. #define RSTCON_SWRST (0x1 << 0)
  54. /* EXYNOS5 */
  55. #define EXYNOS5_PHY_HOST_CTRL0 (0x00)
  56. #define HOST_CTRL0_PHYSWRSTALL (0x1 << 31)
  57. #define HOST_CTRL0_REFCLKSEL_MASK (0x3 << 19)
  58. #define HOST_CTRL0_REFCLKSEL_XTAL (0x0 << 19)
  59. #define HOST_CTRL0_REFCLKSEL_EXTL (0x1 << 19)
  60. #define HOST_CTRL0_REFCLKSEL_CLKCORE (0x2 << 19)
  61. #define HOST_CTRL0_FSEL_MASK (0x7 << 16)
  62. #define HOST_CTRL0_FSEL(_x) ((_x) << 16)
  63. #define FSEL_CLKSEL_50M (0x7)
  64. #define FSEL_CLKSEL_24M (0x5)
  65. #define FSEL_CLKSEL_20M (0x4)
  66. #define FSEL_CLKSEL_19200K (0x3)
  67. #define FSEL_CLKSEL_12M (0x2)
  68. #define FSEL_CLKSEL_10M (0x1)
  69. #define FSEL_CLKSEL_9600K (0x0)
  70. #define HOST_CTRL0_TESTBURNIN (0x1 << 11)
  71. #define HOST_CTRL0_RETENABLE (0x1 << 10)
  72. #define HOST_CTRL0_COMMONON_N (0x1 << 9)
  73. #define HOST_CTRL0_SIDDQ (0x1 << 6)
  74. #define HOST_CTRL0_FORCESLEEP (0x1 << 5)
  75. #define HOST_CTRL0_FORCESUSPEND (0x1 << 4)
  76. #define HOST_CTRL0_WORDINTERFACE (0x1 << 3)
  77. #define HOST_CTRL0_UTMISWRST (0x1 << 2)
  78. #define HOST_CTRL0_LINKSWRST (0x1 << 1)
  79. #define HOST_CTRL0_PHYSWRST (0x1 << 0)
  80. #define EXYNOS5_PHY_HOST_TUNE0 (0x04)
  81. #define EXYNOS5_PHY_HSIC_CTRL1 (0x10)
  82. #define EXYNOS5_PHY_HSIC_TUNE1 (0x14)
  83. #define EXYNOS5_PHY_HSIC_CTRL2 (0x20)
  84. #define EXYNOS5_PHY_HSIC_TUNE2 (0x24)
  85. #define HSIC_CTRL_REFCLKSEL_MASK (0x3 << 23)
  86. #define HSIC_CTRL_REFCLKSEL (0x2 << 23)
  87. #define HSIC_CTRL_REFCLKDIV_MASK (0x7f << 16)
  88. #define HSIC_CTRL_REFCLKDIV(_x) ((_x) << 16)
  89. #define HSIC_CTRL_REFCLKDIV_12 (0x24 << 16)
  90. #define HSIC_CTRL_REFCLKDIV_15 (0x1c << 16)
  91. #define HSIC_CTRL_REFCLKDIV_16 (0x1a << 16)
  92. #define HSIC_CTRL_REFCLKDIV_19_2 (0x15 << 16)
  93. #define HSIC_CTRL_REFCLKDIV_20 (0x14 << 16)
  94. #define HSIC_CTRL_SIDDQ (0x1 << 6)
  95. #define HSIC_CTRL_FORCESLEEP (0x1 << 5)
  96. #define HSIC_CTRL_FORCESUSPEND (0x1 << 4)
  97. #define HSIC_CTRL_WORDINTERFACE (0x1 << 3)
  98. #define HSIC_CTRL_UTMISWRST (0x1 << 2)
  99. #define HSIC_CTRL_PHYSWRST (0x1 << 0)
  100. #define EXYNOS5_PHY_HOST_EHCICTRL (0x30)
  101. #define HOST_EHCICTRL_ENAINCRXALIGN (0x1 << 29)
  102. #define HOST_EHCICTRL_ENAINCR4 (0x1 << 28)
  103. #define HOST_EHCICTRL_ENAINCR8 (0x1 << 27)
  104. #define HOST_EHCICTRL_ENAINCR16 (0x1 << 26)
  105. #define EXYNOS5_PHY_HOST_OHCICTRL (0x34)
  106. #define HOST_OHCICTRL_SUSPLGCY (0x1 << 3)
  107. #define HOST_OHCICTRL_APPSTARTCLK (0x1 << 2)
  108. #define HOST_OHCICTRL_CNTSEL (0x1 << 1)
  109. #define HOST_OHCICTRL_CLKCKTRST (0x1 << 0)
  110. #define EXYNOS5_PHY_OTG_SYS (0x38)
  111. #define OTG_SYS_PHYLINK_SWRESET (0x1 << 14)
  112. #define OTG_SYS_LINKSWRST_UOTG (0x1 << 13)
  113. #define OTG_SYS_PHY0_SWRST (0x1 << 12)
  114. #define OTG_SYS_REFCLKSEL_MASK (0x3 << 9)
  115. #define OTG_SYS_REFCLKSEL_XTAL (0x0 << 9)
  116. #define OTG_SYS_REFCLKSEL_EXTL (0x1 << 9)
  117. #define OTG_SYS_REFCLKSEL_CLKCORE (0x2 << 9)
  118. #define OTG_SYS_IDPULLUP_UOTG (0x1 << 8)
  119. #define OTG_SYS_COMMON_ON (0x1 << 7)
  120. #define OTG_SYS_FSEL_MASK (0x7 << 4)
  121. #define OTG_SYS_FSEL(_x) ((_x) << 4)
  122. #define OTG_SYS_FORCESLEEP (0x1 << 3)
  123. #define OTG_SYS_OTGDISABLE (0x1 << 2)
  124. #define OTG_SYS_SIDDQ_UOTG (0x1 << 1)
  125. #define OTG_SYS_FORCESUSPEND (0x1 << 0)
  126. #define EXYNOS5_PHY_OTG_TUNE (0x40)
  127. #ifndef MHZ
  128. #define MHZ (1000*1000)
  129. #endif
  130. #ifndef KHZ
  131. #define KHZ (1000)
  132. #endif
  133. #define EXYNOS_USBHOST_PHY_CTRL_OFFSET (0x4)
  134. #define S3C64XX_USBPHY_ENABLE (0x1 << 16)
  135. #define EXYNOS_USBPHY_ENABLE (0x1 << 0)
  136. #define EXYNOS_USB20PHY_CFG_HOST_LINK (0x1 << 0)
  137. enum samsung_cpu_type {
  138. TYPE_S3C64XX,
  139. TYPE_EXYNOS4210,
  140. TYPE_EXYNOS5250,
  141. };
  142. /*
  143. * struct samsung_usbphy_drvdata - driver data for various SoC variants
  144. * @cpu_type: machine identifier
  145. * @devphy_en_mask: device phy enable mask for PHY CONTROL register
  146. * @hostphy_en_mask: host phy enable mask for PHY CONTROL register
  147. * @devphy_reg_offset: offset to DEVICE PHY CONTROL register from
  148. * mapped address of system controller.
  149. * @hostphy_reg_offset: offset to HOST PHY CONTROL register from
  150. * mapped address of system controller.
  151. *
  152. * Here we have a separate mask for device type phy.
  153. * Having different masks for host and device type phy helps
  154. * in setting independent masks in case of SoCs like S5PV210,
  155. * in which PHY0 and PHY1 enable bits belong to same register
  156. * placed at position 0 and 1 respectively.
  157. * Although for newer SoCs like exynos these bits belong to
  158. * different registers altogether placed at position 0.
  159. */
  160. struct samsung_usbphy_drvdata {
  161. int cpu_type;
  162. int devphy_en_mask;
  163. int hostphy_en_mask;
  164. u32 devphy_reg_offset;
  165. u32 hostphy_reg_offset;
  166. };
  167. /*
  168. * struct samsung_usbphy - transceiver driver state
  169. * @phy: transceiver structure
  170. * @plat: platform data
  171. * @dev: The parent device supplied to the probe function
  172. * @clk: usb phy clock
  173. * @regs: usb phy controller registers memory base
  174. * @pmuregs: USB device PHY_CONTROL register memory base
  175. * @sysreg: USB2.0 PHY_CFG register memory base
  176. * @ref_clk_freq: reference clock frequency selection
  177. * @drv_data: driver data available for different SoCs
  178. * @phy_type: Samsung SoCs specific phy types: #HOST
  179. * #DEVICE
  180. * @phy_usage: usage count for phy
  181. * @lock: lock for phy operations
  182. */
  183. struct samsung_usbphy {
  184. struct usb_phy phy;
  185. struct samsung_usbphy_data *plat;
  186. struct device *dev;
  187. struct clk *clk;
  188. void __iomem *regs;
  189. void __iomem *pmuregs;
  190. void __iomem *sysreg;
  191. int ref_clk_freq;
  192. const struct samsung_usbphy_drvdata *drv_data;
  193. enum samsung_usb_phy_type phy_type;
  194. atomic_t phy_usage;
  195. spinlock_t lock;
  196. };
  197. #define phy_to_sphy(x) container_of((x), struct samsung_usbphy, phy)
  198. int samsung_usbphy_set_host(struct usb_otg *otg, struct usb_bus *host)
  199. {
  200. if (!otg)
  201. return -ENODEV;
  202. if (!otg->host)
  203. otg->host = host;
  204. return 0;
  205. }
  206. static int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy)
  207. {
  208. struct device_node *usbphy_sys;
  209. /* Getting node for system controller interface for usb-phy */
  210. usbphy_sys = of_get_child_by_name(sphy->dev->of_node, "usbphy-sys");
  211. if (!usbphy_sys) {
  212. dev_err(sphy->dev, "No sys-controller interface for usb-phy\n");
  213. return -ENODEV;
  214. }
  215. sphy->pmuregs = of_iomap(usbphy_sys, 0);
  216. if (sphy->pmuregs == NULL) {
  217. dev_err(sphy->dev, "Can't get usb-phy pmu control register\n");
  218. goto err0;
  219. }
  220. sphy->sysreg = of_iomap(usbphy_sys, 1);
  221. /*
  222. * Not returning error code here, since this situation is not fatal.
  223. * Few SoCs may not have this switch available
  224. */
  225. if (sphy->sysreg == NULL)
  226. dev_warn(sphy->dev, "Can't get usb-phy sysreg cfg register\n");
  227. of_node_put(usbphy_sys);
  228. return 0;
  229. err0:
  230. of_node_put(usbphy_sys);
  231. return -ENXIO;
  232. }
  233. /*
  234. * Set isolation here for phy.
  235. * Here 'on = true' would mean USB PHY block is isolated, hence
  236. * de-activated and vice-versa.
  237. */
  238. static void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on)
  239. {
  240. void __iomem *reg = NULL;
  241. u32 reg_val;
  242. u32 en_mask = 0;
  243. if (!sphy->pmuregs) {
  244. dev_warn(sphy->dev, "Can't set pmu isolation\n");
  245. return;
  246. }
  247. switch (sphy->drv_data->cpu_type) {
  248. case TYPE_S3C64XX:
  249. /*
  250. * Do nothing: We will add here once S3C64xx goes for DT support
  251. */
  252. break;
  253. case TYPE_EXYNOS4210:
  254. /*
  255. * Fall through since exynos4210 and exynos5250 have similar
  256. * register architecture: two separate registers for host and
  257. * device phy control with enable bit at position 0.
  258. */
  259. case TYPE_EXYNOS5250:
  260. if (sphy->phy_type == USB_PHY_TYPE_DEVICE) {
  261. reg = sphy->pmuregs +
  262. sphy->drv_data->devphy_reg_offset;
  263. en_mask = sphy->drv_data->devphy_en_mask;
  264. } else if (sphy->phy_type == USB_PHY_TYPE_HOST) {
  265. reg = sphy->pmuregs +
  266. sphy->drv_data->hostphy_reg_offset;
  267. en_mask = sphy->drv_data->hostphy_en_mask;
  268. }
  269. break;
  270. default:
  271. dev_err(sphy->dev, "Invalid SoC type\n");
  272. return;
  273. }
  274. reg_val = readl(reg);
  275. if (on)
  276. reg_val &= ~en_mask;
  277. else
  278. reg_val |= en_mask;
  279. writel(reg_val, reg);
  280. }
  281. /*
  282. * Configure the mode of working of usb-phy here: HOST/DEVICE.
  283. */
  284. static void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy)
  285. {
  286. u32 reg;
  287. if (!sphy->sysreg) {
  288. dev_warn(sphy->dev, "Can't configure specified phy mode\n");
  289. return;
  290. }
  291. reg = readl(sphy->sysreg);
  292. if (sphy->phy_type == USB_PHY_TYPE_DEVICE)
  293. reg &= ~EXYNOS_USB20PHY_CFG_HOST_LINK;
  294. else if (sphy->phy_type == USB_PHY_TYPE_HOST)
  295. reg |= EXYNOS_USB20PHY_CFG_HOST_LINK;
  296. writel(reg, sphy->sysreg);
  297. }
  298. /*
  299. * PHYs are different for USB Device and USB Host.
  300. * This make sure that correct PHY type is selected before
  301. * any operation on PHY.
  302. */
  303. static int samsung_usbphy_set_type(struct usb_phy *phy,
  304. enum samsung_usb_phy_type phy_type)
  305. {
  306. struct samsung_usbphy *sphy = phy_to_sphy(phy);
  307. sphy->phy_type = phy_type;
  308. return 0;
  309. }
  310. /*
  311. * Returns reference clock frequency selection value
  312. */
  313. static int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy)
  314. {
  315. struct clk *ref_clk;
  316. int refclk_freq = 0;
  317. /*
  318. * In exynos5250 USB host and device PHY use
  319. * external crystal clock XXTI
  320. */
  321. if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
  322. ref_clk = clk_get(sphy->dev, "ext_xtal");
  323. else
  324. ref_clk = clk_get(sphy->dev, "xusbxti");
  325. if (IS_ERR(ref_clk)) {
  326. dev_err(sphy->dev, "Failed to get reference clock\n");
  327. return PTR_ERR(ref_clk);
  328. }
  329. if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) {
  330. /* set clock frequency for PLL */
  331. switch (clk_get_rate(ref_clk)) {
  332. case 9600 * KHZ:
  333. refclk_freq = FSEL_CLKSEL_9600K;
  334. break;
  335. case 10 * MHZ:
  336. refclk_freq = FSEL_CLKSEL_10M;
  337. break;
  338. case 12 * MHZ:
  339. refclk_freq = FSEL_CLKSEL_12M;
  340. break;
  341. case 19200 * KHZ:
  342. refclk_freq = FSEL_CLKSEL_19200K;
  343. break;
  344. case 20 * MHZ:
  345. refclk_freq = FSEL_CLKSEL_20M;
  346. break;
  347. case 50 * MHZ:
  348. refclk_freq = FSEL_CLKSEL_50M;
  349. break;
  350. case 24 * MHZ:
  351. default:
  352. /* default reference clock */
  353. refclk_freq = FSEL_CLKSEL_24M;
  354. break;
  355. }
  356. } else {
  357. switch (clk_get_rate(ref_clk)) {
  358. case 12 * MHZ:
  359. refclk_freq = PHYCLK_CLKSEL_12M;
  360. break;
  361. case 24 * MHZ:
  362. refclk_freq = PHYCLK_CLKSEL_24M;
  363. break;
  364. case 48 * MHZ:
  365. refclk_freq = PHYCLK_CLKSEL_48M;
  366. break;
  367. default:
  368. if (sphy->drv_data->cpu_type == TYPE_S3C64XX)
  369. refclk_freq = PHYCLK_CLKSEL_48M;
  370. else
  371. refclk_freq = PHYCLK_CLKSEL_24M;
  372. break;
  373. }
  374. }
  375. clk_put(ref_clk);
  376. return refclk_freq;
  377. }
  378. static bool exynos5_phyhost_is_on(void *regs)
  379. {
  380. u32 reg;
  381. reg = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
  382. return !(reg & HOST_CTRL0_SIDDQ);
  383. }
  384. static void samsung_exynos5_usbphy_enable(struct samsung_usbphy *sphy)
  385. {
  386. void __iomem *regs = sphy->regs;
  387. u32 phyclk = sphy->ref_clk_freq;
  388. u32 phyhost;
  389. u32 phyotg;
  390. u32 phyhsic;
  391. u32 ehcictrl;
  392. u32 ohcictrl;
  393. /*
  394. * phy_usage helps in keeping usage count for phy
  395. * so that the first consumer enabling the phy is also
  396. * the last consumer to disable it.
  397. */
  398. atomic_inc(&sphy->phy_usage);
  399. if (exynos5_phyhost_is_on(regs)) {
  400. dev_info(sphy->dev, "Already power on PHY\n");
  401. return;
  402. }
  403. /* Host configuration */
  404. phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
  405. /* phy reference clock configuration */
  406. phyhost &= ~HOST_CTRL0_FSEL_MASK;
  407. phyhost |= HOST_CTRL0_FSEL(phyclk);
  408. /* host phy reset */
  409. phyhost &= ~(HOST_CTRL0_PHYSWRST |
  410. HOST_CTRL0_PHYSWRSTALL |
  411. HOST_CTRL0_SIDDQ |
  412. /* Enable normal mode of operation */
  413. HOST_CTRL0_FORCESUSPEND |
  414. HOST_CTRL0_FORCESLEEP);
  415. /* Link reset */
  416. phyhost |= (HOST_CTRL0_LINKSWRST |
  417. HOST_CTRL0_UTMISWRST |
  418. /* COMMON Block configuration during suspend */
  419. HOST_CTRL0_COMMONON_N);
  420. writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
  421. udelay(10);
  422. phyhost &= ~(HOST_CTRL0_LINKSWRST |
  423. HOST_CTRL0_UTMISWRST);
  424. writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
  425. /* OTG configuration */
  426. phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS);
  427. /* phy reference clock configuration */
  428. phyotg &= ~OTG_SYS_FSEL_MASK;
  429. phyotg |= OTG_SYS_FSEL(phyclk);
  430. /* Enable normal mode of operation */
  431. phyotg &= ~(OTG_SYS_FORCESUSPEND |
  432. OTG_SYS_SIDDQ_UOTG |
  433. OTG_SYS_FORCESLEEP |
  434. OTG_SYS_REFCLKSEL_MASK |
  435. /* COMMON Block configuration during suspend */
  436. OTG_SYS_COMMON_ON);
  437. /* OTG phy & link reset */
  438. phyotg |= (OTG_SYS_PHY0_SWRST |
  439. OTG_SYS_LINKSWRST_UOTG |
  440. OTG_SYS_PHYLINK_SWRESET |
  441. OTG_SYS_OTGDISABLE |
  442. /* Set phy refclk */
  443. OTG_SYS_REFCLKSEL_CLKCORE);
  444. writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
  445. udelay(10);
  446. phyotg &= ~(OTG_SYS_PHY0_SWRST |
  447. OTG_SYS_LINKSWRST_UOTG |
  448. OTG_SYS_PHYLINK_SWRESET);
  449. writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
  450. /* HSIC phy configuration */
  451. phyhsic = (HSIC_CTRL_REFCLKDIV_12 |
  452. HSIC_CTRL_REFCLKSEL |
  453. HSIC_CTRL_PHYSWRST);
  454. writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
  455. writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
  456. udelay(10);
  457. phyhsic &= ~HSIC_CTRL_PHYSWRST;
  458. writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
  459. writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
  460. udelay(80);
  461. /* enable EHCI DMA burst */
  462. ehcictrl = readl(regs + EXYNOS5_PHY_HOST_EHCICTRL);
  463. ehcictrl |= (HOST_EHCICTRL_ENAINCRXALIGN |
  464. HOST_EHCICTRL_ENAINCR4 |
  465. HOST_EHCICTRL_ENAINCR8 |
  466. HOST_EHCICTRL_ENAINCR16);
  467. writel(ehcictrl, regs + EXYNOS5_PHY_HOST_EHCICTRL);
  468. /* set ohci_suspend_on_n */
  469. ohcictrl = readl(regs + EXYNOS5_PHY_HOST_OHCICTRL);
  470. ohcictrl |= HOST_OHCICTRL_SUSPLGCY;
  471. writel(ohcictrl, regs + EXYNOS5_PHY_HOST_OHCICTRL);
  472. }
  473. static void samsung_usbphy_enable(struct samsung_usbphy *sphy)
  474. {
  475. void __iomem *regs = sphy->regs;
  476. u32 phypwr;
  477. u32 phyclk;
  478. u32 rstcon;
  479. /* set clock frequency for PLL */
  480. phyclk = sphy->ref_clk_freq;
  481. phypwr = readl(regs + SAMSUNG_PHYPWR);
  482. rstcon = readl(regs + SAMSUNG_RSTCON);
  483. switch (sphy->drv_data->cpu_type) {
  484. case TYPE_S3C64XX:
  485. phyclk &= ~PHYCLK_COMMON_ON_N;
  486. phypwr &= ~PHYPWR_NORMAL_MASK;
  487. rstcon |= RSTCON_SWRST;
  488. break;
  489. case TYPE_EXYNOS4210:
  490. phypwr &= ~PHYPWR_NORMAL_MASK_PHY0;
  491. rstcon |= RSTCON_SWRST;
  492. default:
  493. break;
  494. }
  495. writel(phyclk, regs + SAMSUNG_PHYCLK);
  496. /* Configure PHY0 for normal operation*/
  497. writel(phypwr, regs + SAMSUNG_PHYPWR);
  498. /* reset all ports of PHY and Link */
  499. writel(rstcon, regs + SAMSUNG_RSTCON);
  500. udelay(10);
  501. rstcon &= ~RSTCON_SWRST;
  502. writel(rstcon, regs + SAMSUNG_RSTCON);
  503. }
  504. static void samsung_exynos5_usbphy_disable(struct samsung_usbphy *sphy)
  505. {
  506. void __iomem *regs = sphy->regs;
  507. u32 phyhost;
  508. u32 phyotg;
  509. u32 phyhsic;
  510. if (atomic_dec_return(&sphy->phy_usage) > 0) {
  511. dev_info(sphy->dev, "still being used\n");
  512. return;
  513. }
  514. phyhsic = (HSIC_CTRL_REFCLKDIV_12 |
  515. HSIC_CTRL_REFCLKSEL |
  516. HSIC_CTRL_SIDDQ |
  517. HSIC_CTRL_FORCESLEEP |
  518. HSIC_CTRL_FORCESUSPEND);
  519. writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
  520. writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
  521. phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
  522. phyhost |= (HOST_CTRL0_SIDDQ |
  523. HOST_CTRL0_FORCESUSPEND |
  524. HOST_CTRL0_FORCESLEEP |
  525. HOST_CTRL0_PHYSWRST |
  526. HOST_CTRL0_PHYSWRSTALL);
  527. writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
  528. phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS);
  529. phyotg |= (OTG_SYS_FORCESUSPEND |
  530. OTG_SYS_SIDDQ_UOTG |
  531. OTG_SYS_FORCESLEEP);
  532. writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
  533. }
  534. static void samsung_usbphy_disable(struct samsung_usbphy *sphy)
  535. {
  536. void __iomem *regs = sphy->regs;
  537. u32 phypwr;
  538. phypwr = readl(regs + SAMSUNG_PHYPWR);
  539. switch (sphy->drv_data->cpu_type) {
  540. case TYPE_S3C64XX:
  541. phypwr |= PHYPWR_NORMAL_MASK;
  542. break;
  543. case TYPE_EXYNOS4210:
  544. phypwr |= PHYPWR_NORMAL_MASK_PHY0;
  545. default:
  546. break;
  547. }
  548. /* Disable analog and otg block power */
  549. writel(phypwr, regs + SAMSUNG_PHYPWR);
  550. }
  551. /*
  552. * The function passed to the usb driver for phy initialization
  553. */
  554. static int samsung_usbphy_init(struct usb_phy *phy)
  555. {
  556. struct samsung_usbphy *sphy;
  557. struct usb_bus *host = NULL;
  558. unsigned long flags;
  559. int ret = 0;
  560. sphy = phy_to_sphy(phy);
  561. host = phy->otg->host;
  562. /* Enable the phy clock */
  563. ret = clk_prepare_enable(sphy->clk);
  564. if (ret) {
  565. dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
  566. return ret;
  567. }
  568. spin_lock_irqsave(&sphy->lock, flags);
  569. if (host) {
  570. /* setting default phy-type for USB 2.0 */
  571. if (!strstr(dev_name(host->controller), "ehci") ||
  572. !strstr(dev_name(host->controller), "ohci"))
  573. samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST);
  574. } else {
  575. samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
  576. }
  577. /* Disable phy isolation */
  578. if (sphy->plat && sphy->plat->pmu_isolation)
  579. sphy->plat->pmu_isolation(false);
  580. else
  581. samsung_usbphy_set_isolation(sphy, false);
  582. /* Selecting Host/OTG mode; After reset USB2.0PHY_CFG: HOST */
  583. samsung_usbphy_cfg_sel(sphy);
  584. /* Initialize usb phy registers */
  585. if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
  586. samsung_exynos5_usbphy_enable(sphy);
  587. else
  588. samsung_usbphy_enable(sphy);
  589. spin_unlock_irqrestore(&sphy->lock, flags);
  590. /* Disable the phy clock */
  591. clk_disable_unprepare(sphy->clk);
  592. return ret;
  593. }
  594. /*
  595. * The function passed to the usb driver for phy shutdown
  596. */
  597. static void samsung_usbphy_shutdown(struct usb_phy *phy)
  598. {
  599. struct samsung_usbphy *sphy;
  600. struct usb_bus *host = NULL;
  601. unsigned long flags;
  602. sphy = phy_to_sphy(phy);
  603. host = phy->otg->host;
  604. if (clk_prepare_enable(sphy->clk)) {
  605. dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
  606. return;
  607. }
  608. spin_lock_irqsave(&sphy->lock, flags);
  609. if (host) {
  610. /* setting default phy-type for USB 2.0 */
  611. if (!strstr(dev_name(host->controller), "ehci") ||
  612. !strstr(dev_name(host->controller), "ohci"))
  613. samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST);
  614. } else {
  615. samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
  616. }
  617. /* De-initialize usb phy registers */
  618. if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
  619. samsung_exynos5_usbphy_disable(sphy);
  620. else
  621. samsung_usbphy_disable(sphy);
  622. /* Enable phy isolation */
  623. if (sphy->plat && sphy->plat->pmu_isolation)
  624. sphy->plat->pmu_isolation(true);
  625. else
  626. samsung_usbphy_set_isolation(sphy, true);
  627. spin_unlock_irqrestore(&sphy->lock, flags);
  628. clk_disable_unprepare(sphy->clk);
  629. }
  630. static const struct of_device_id samsung_usbphy_dt_match[];
  631. static inline const struct samsung_usbphy_drvdata
  632. *samsung_usbphy_get_driver_data(struct platform_device *pdev)
  633. {
  634. if (pdev->dev.of_node) {
  635. const struct of_device_id *match;
  636. match = of_match_node(samsung_usbphy_dt_match,
  637. pdev->dev.of_node);
  638. return match->data;
  639. }
  640. return (struct samsung_usbphy_drvdata *)
  641. platform_get_device_id(pdev)->driver_data;
  642. }
  643. static int samsung_usbphy_probe(struct platform_device *pdev)
  644. {
  645. struct samsung_usbphy *sphy;
  646. struct usb_otg *otg;
  647. struct samsung_usbphy_data *pdata = pdev->dev.platform_data;
  648. const struct samsung_usbphy_drvdata *drv_data;
  649. struct device *dev = &pdev->dev;
  650. struct resource *phy_mem;
  651. void __iomem *phy_base;
  652. struct clk *clk;
  653. int ret;
  654. phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  655. if (!phy_mem) {
  656. dev_err(dev, "%s: missing mem resource\n", __func__);
  657. return -ENODEV;
  658. }
  659. phy_base = devm_ioremap_resource(dev, phy_mem);
  660. if (IS_ERR(phy_base))
  661. return PTR_ERR(phy_base);
  662. sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL);
  663. if (!sphy)
  664. return -ENOMEM;
  665. otg = devm_kzalloc(dev, sizeof(*otg), GFP_KERNEL);
  666. if (!otg)
  667. return -ENOMEM;
  668. drv_data = samsung_usbphy_get_driver_data(pdev);
  669. if (drv_data->cpu_type == TYPE_EXYNOS5250)
  670. clk = devm_clk_get(dev, "usbhost");
  671. else
  672. clk = devm_clk_get(dev, "otg");
  673. if (IS_ERR(clk)) {
  674. dev_err(dev, "Failed to get otg clock\n");
  675. return PTR_ERR(clk);
  676. }
  677. sphy->dev = dev;
  678. if (dev->of_node) {
  679. ret = samsung_usbphy_parse_dt(sphy);
  680. if (ret < 0)
  681. return ret;
  682. } else {
  683. if (!pdata) {
  684. dev_err(dev, "no platform data specified\n");
  685. return -EINVAL;
  686. }
  687. }
  688. sphy->plat = pdata;
  689. sphy->regs = phy_base;
  690. sphy->clk = clk;
  691. sphy->drv_data = drv_data;
  692. sphy->phy.dev = sphy->dev;
  693. sphy->phy.label = "samsung-usbphy";
  694. sphy->phy.init = samsung_usbphy_init;
  695. sphy->phy.shutdown = samsung_usbphy_shutdown;
  696. sphy->ref_clk_freq = samsung_usbphy_get_refclk_freq(sphy);
  697. sphy->phy.otg = otg;
  698. sphy->phy.otg->phy = &sphy->phy;
  699. sphy->phy.otg->set_host = samsung_usbphy_set_host;
  700. spin_lock_init(&sphy->lock);
  701. platform_set_drvdata(pdev, sphy);
  702. return usb_add_phy(&sphy->phy, USB_PHY_TYPE_USB2);
  703. }
  704. static int samsung_usbphy_remove(struct platform_device *pdev)
  705. {
  706. struct samsung_usbphy *sphy = platform_get_drvdata(pdev);
  707. usb_remove_phy(&sphy->phy);
  708. if (sphy->pmuregs)
  709. iounmap(sphy->pmuregs);
  710. if (sphy->sysreg)
  711. iounmap(sphy->sysreg);
  712. return 0;
  713. }
  714. static const struct samsung_usbphy_drvdata usbphy_s3c64xx = {
  715. .cpu_type = TYPE_S3C64XX,
  716. .devphy_en_mask = S3C64XX_USBPHY_ENABLE,
  717. };
  718. static const struct samsung_usbphy_drvdata usbphy_exynos4 = {
  719. .cpu_type = TYPE_EXYNOS4210,
  720. .devphy_en_mask = EXYNOS_USBPHY_ENABLE,
  721. .hostphy_en_mask = EXYNOS_USBPHY_ENABLE,
  722. };
  723. static struct samsung_usbphy_drvdata usbphy_exynos5 = {
  724. .cpu_type = TYPE_EXYNOS5250,
  725. .hostphy_en_mask = EXYNOS_USBPHY_ENABLE,
  726. .hostphy_reg_offset = EXYNOS_USBHOST_PHY_CTRL_OFFSET,
  727. };
  728. #ifdef CONFIG_OF
  729. static const struct of_device_id samsung_usbphy_dt_match[] = {
  730. {
  731. .compatible = "samsung,s3c64xx-usbphy",
  732. .data = &usbphy_s3c64xx,
  733. }, {
  734. .compatible = "samsung,exynos4210-usbphy",
  735. .data = &usbphy_exynos4,
  736. }, {
  737. .compatible = "samsung,exynos5250-usbphy",
  738. .data = &usbphy_exynos5
  739. },
  740. {},
  741. };
  742. MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match);
  743. #endif
  744. static struct platform_device_id samsung_usbphy_driver_ids[] = {
  745. {
  746. .name = "s3c64xx-usbphy",
  747. .driver_data = (unsigned long)&usbphy_s3c64xx,
  748. }, {
  749. .name = "exynos4210-usbphy",
  750. .driver_data = (unsigned long)&usbphy_exynos4,
  751. }, {
  752. .name = "exynos5250-usbphy",
  753. .driver_data = (unsigned long)&usbphy_exynos5,
  754. },
  755. {},
  756. };
  757. MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids);
  758. static struct platform_driver samsung_usbphy_driver = {
  759. .probe = samsung_usbphy_probe,
  760. .remove = samsung_usbphy_remove,
  761. .id_table = samsung_usbphy_driver_ids,
  762. .driver = {
  763. .name = "samsung-usbphy",
  764. .owner = THIS_MODULE,
  765. .of_match_table = of_match_ptr(samsung_usbphy_dt_match),
  766. },
  767. };
  768. module_platform_driver(samsung_usbphy_driver);
  769. MODULE_DESCRIPTION("Samsung USB phy controller");
  770. MODULE_AUTHOR("Praveen Paneri <p.paneri@samsung.com>");
  771. MODULE_LICENSE("GPL");
  772. MODULE_ALIAS("platform:samsung-usbphy");