0001-pcmcia-Add-Hitachi-HD6446x-PCMCIA-socket-support.patch 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720
  1. From b6ffbcb525539139a9b2255b992622f92757ea37 Mon Sep 17 00:00:00 2001
  2. From: Artur Rojek <contact@artur-rojek.eu>
  3. Date: Fri, 1 Aug 2025 22:52:22 +0200
  4. Subject: [PATCH] pcmcia: Add Hitachi HD6446x PCMCIA socket support
  5. Introduce support for the PC Card Controller part of the Hitachi HD6446x
  6. series of Intelligent Peripheral Controllers.
  7. WIP code. DO NOT UPSTREAM!
  8. ---
  9. arch/sh/boards/mach-hp6xx/setup.c | 45 ++-
  10. arch/sh/cchips/hd6446x/hd64461.c | 56 +++-
  11. arch/sh/include/asm/hd64461.h | 6 +-
  12. drivers/pcmcia/Kconfig | 7 +
  13. drivers/pcmcia/Makefile | 1 +
  14. drivers/pcmcia/hd6446x_pcc.c | 453 ++++++++++++++++++++++++++++++
  15. include/pcmcia/hd6446x_pcc.h | 9 +
  16. 7 files changed, 569 insertions(+), 8 deletions(-)
  17. create mode 100644 drivers/pcmcia/hd6446x_pcc.c
  18. create mode 100644 include/pcmcia/hd6446x_pcc.h
  19. diff --git a/arch/sh/boards/mach-hp6xx/setup.c b/arch/sh/boards/mach-hp6xx/setup.c
  20. index 2ceead68d7bf..c697b8e1f5ac 100644
  21. --- a/arch/sh/boards/mach-hp6xx/setup.c
  22. +++ b/arch/sh/boards/mach-hp6xx/setup.c
  23. @@ -18,19 +18,23 @@
  24. #include <mach/hp6xx.h>
  25. #include <cpu/dac.h>
  26. +#include <pcmcia/hd6446x_pcc.h>
  27. +
  28. #define SCPCR 0xa4000116
  29. #define SCPDR 0xa4000136
  30. +#define CF_MEM_ATTR (0x15000000 - 0)
  31. +
  32. /* CF Slot */
  33. static struct resource cf_ide_resources[] = {
  34. [0] = {
  35. - .start = 0x15000000 + 0x1f0,
  36. - .end = 0x15000000 + 0x1f0 + 0x08 - 0x01,
  37. + .start = CF_MEM_ATTR + 0x1f0,
  38. + .end = CF_MEM_ATTR + 0x1f0 + 0x08 - 0x01,
  39. .flags = IORESOURCE_MEM,
  40. },
  41. [1] = {
  42. - .start = 0x15000000 + 0x1fe,
  43. - .end = 0x15000000 + 0x1fe + 0x01,
  44. + .start = CF_MEM_ATTR + 0x1fe,
  45. + .end = CF_MEM_ATTR + 0x1fe + 0x01,
  46. .flags = IORESOURCE_MEM,
  47. },
  48. [2] = {
  49. @@ -51,6 +55,36 @@ static struct platform_device jornadakbd_device = {
  50. .id = -1,
  51. };
  52. +static struct resource hd6446x_pcc_resources[] = {
  53. + [0] = {
  54. + .start = HD64461_PCC0ISR,
  55. + .end = HD64461_PCC0ISR + 0x10,
  56. + .flags = IORESOURCE_MEM,
  57. + },
  58. + [1] = {
  59. + .start = HD64461_PCC0_BASE,
  60. + .end = HD64461_PCC0_BASE + 0x4000000,
  61. + .flags = IORESOURCE_MEM,
  62. + },
  63. + [2] = {
  64. + .start = HD64461_IRQ_PCC0,
  65. + .flags = IORESOURCE_IRQ,
  66. + },
  67. +};
  68. +
  69. +static struct hd6446x_pcc_plat_data hd6446x_pcc_platform_data = {
  70. + .slot_id = 1,
  71. + .io_support = true,
  72. +};
  73. +
  74. +static struct platform_device hp6446x_pcc_device = {
  75. + .name = "hd6446x_pcc",
  76. + .id = -1,
  77. + .num_resources = ARRAY_SIZE(hd6446x_pcc_resources),
  78. + .resource = hd6446x_pcc_resources,
  79. + .dev.platform_data = &hd6446x_pcc_platform_data,
  80. +};
  81. +
  82. static void dac_audio_start(struct dac_audio_pdata *pdata)
  83. {
  84. u16 v;
  85. @@ -108,6 +142,7 @@ static struct platform_device *hp6xx_devices[] __initdata = {
  86. &cf_ide_device,
  87. &jornadakbd_device,
  88. &dac_audio_device,
  89. + &hp6446x_pcc_device,
  90. };
  91. static void __init hp6xx_init_irq(void)
  92. @@ -126,6 +161,8 @@ static void __init hp6xx_setup(char **cmdline_p)
  93. u8 v8;
  94. u16 v;
  95. + __set_io_port_base(0);
  96. +
  97. v = inw(HD64461_STBCR);
  98. v |= HD64461_STBCR_SURTST | HD64461_STBCR_SIRST |
  99. HD64461_STBCR_STM1ST | HD64461_STBCR_STM0ST |
  100. diff --git a/arch/sh/cchips/hd6446x/hd64461.c b/arch/sh/cchips/hd6446x/hd64461.c
  101. index 81764882d87d..965486584ee5 100644
  102. --- a/arch/sh/cchips/hd6446x/hd64461.c
  103. +++ b/arch/sh/cchips/hd6446x/hd64461.c
  104. @@ -4,7 +4,9 @@
  105. * Hitachi HD64461 companion chip support
  106. */
  107. +#include <linux/clkdev.h>
  108. #include <linux/sched.h>
  109. +#include <linux/sh_clk.h>
  110. #include <linux/module.h>
  111. #include <linux/kernel.h>
  112. #include <linux/param.h>
  113. @@ -45,7 +47,7 @@ static void hd64461_mask_and_ack_irq(struct irq_data *data)
  114. hd64461_mask_irq(data);
  115. #ifdef CONFIG_HD64461_ENABLER
  116. - if (data->irq == HD64461_IRQBASE + 13)
  117. + if (data->irq == HD64461_IRQ_PCC1)
  118. __raw_writeb(0x00, HD64461_PCC1CSCR);
  119. #endif
  120. }
  121. @@ -72,6 +74,51 @@ static void hd64461_irq_demux(struct irq_desc *desc)
  122. }
  123. }
  124. +static int hd64461_clk_enable(struct clk *clk)
  125. +{
  126. + u16 reg = __raw_readw(HD64461_STBCR);
  127. +
  128. + printk("clk enable: %d\n", clk->enable_bit);
  129. +
  130. + __raw_writew(reg & ~(1 << clk->enable_bit), HD64461_STBCR);
  131. +
  132. + return 0;
  133. +}
  134. +
  135. +static void hd64461_clk_disable(struct clk *clk)
  136. +{
  137. + u16 reg = __raw_readw(HD64461_STBCR);
  138. +
  139. + printk("clk disable: %d\n", clk->enable_bit);
  140. + //panic("clk disable: %d\n", clk->enable_bit);
  141. +
  142. +
  143. + __raw_writew(reg | (1 << clk->enable_bit), HD64461_STBCR);
  144. +}
  145. +
  146. +static struct sh_clk_ops hd64461_clk_ops = {
  147. + .enable = hd64461_clk_enable,
  148. + .disable = hd64461_clk_disable,
  149. +};
  150. +
  151. +static struct clk hd64461_clk[] = {
  152. + {
  153. + .enable_bit = 5,
  154. + .ops = &hd64461_clk_ops,
  155. + .flags = CLK_ENABLE_ON_INIT,
  156. + },
  157. + {
  158. + .enable_bit = 6,
  159. + .ops = &hd64461_clk_ops,
  160. + .flags = CLK_ENABLE_ON_INIT,
  161. + },
  162. +};
  163. +
  164. +static struct clk_lookup hd64461_clk_lookup[] = {
  165. + CLKDEV_CON_ID("pcc1", &hd64461_clk[0]),
  166. + CLKDEV_CON_ID("pcc0", &hd64461_clk[1]),
  167. +};
  168. +
  169. static int __init setup_hd64461(void)
  170. {
  171. int irq_base, i;
  172. @@ -106,6 +153,13 @@ static int __init setup_hd64461(void)
  173. __raw_writeb(0x00, HD64461_PCC1CSCR);
  174. #endif
  175. +// for (i = 0; i < ARRAY_SIZE(hd64461_clk); i++)
  176. +// clk_register(&hd64461_clk[i]);
  177. + clk_register(&hd64461_clk[1]);
  178. + clkdev_add_table(hd64461_clk_lookup, ARRAY_SIZE(hd64461_clk_lookup));
  179. +
  180. + printk("done with clk setup\n");
  181. +
  182. return 0;
  183. }
  184. diff --git a/arch/sh/include/asm/hd64461.h b/arch/sh/include/asm/hd64461.h
  185. index d2c485fa333b..91823ec07f79 100644
  186. --- a/arch/sh/include/asm/hd64461.h
  187. +++ b/arch/sh/include/asm/hd64461.h
  188. @@ -17,9 +17,9 @@
  189. #define HD64461_IOBASE 0xb0000000
  190. #define HD64461_IO_OFFSET(x) (HD64461_IOBASE + (x))
  191. #define HD64461_PCC0_BASE HD64461_IO_OFFSET(0x8000000)
  192. -#define HD64461_PCC0_ATTR (HD64461_PCC0_BASE) /* 0xb80000000 */
  193. -#define HD64461_PCC0_COMM (HD64461_PCC0_BASE+HD64461_PCC_WINDOW) /* 0xb90000000 */
  194. -#define HD64461_PCC0_IO (HD64461_PCC0_BASE+2*HD64461_PCC_WINDOW) /* 0xba0000000 */
  195. +#define HD64461_PCC0_ATTR (HD64461_PCC0_BASE) /* 0xb8000000 */
  196. +#define HD64461_PCC0_COMM (HD64461_PCC0_BASE+HD64461_PCC_WINDOW) /* 0xb9000000 */
  197. +#define HD64461_PCC0_IO (HD64461_PCC0_BASE+2*HD64461_PCC_WINDOW) /* 0xba000000 */
  198. /* Area 5 - Slot 1 - memory card only */
  199. #define HD64461_PCC1_BASE HD64461_IO_OFFSET(0x4000000)
  200. diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
  201. index dddb235dd020..f2434ca15c8e 100644
  202. --- a/drivers/pcmcia/Kconfig
  203. +++ b/drivers/pcmcia/Kconfig
  204. @@ -159,6 +159,13 @@ config PCMCIA_ALCHEMY_DEVBOARD
  205. This driver is also available as a module called db1xxx_ss.ko
  206. +config PCMCIA_HD6446X_PCC
  207. + tristate "Hitachi HD6446x PCMCIA socket support"
  208. + depends on PCMCIA && HD6446X_SERIES
  209. + help
  210. + Say Y here to include support for the PC Card Controller part of
  211. + the Hitachi HD6446x series of Intelligent Peripheral Controllers.
  212. +
  213. config PCMCIA_XXS1500
  214. tristate "MyCable XXS1500 PCMCIA socket support"
  215. depends on PCMCIA && MIPS_XXS1500
  216. diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
  217. index c9d51b150682..764df19be544 100644
  218. --- a/drivers/pcmcia/Makefile
  219. +++ b/drivers/pcmcia/Makefile
  220. @@ -33,6 +33,7 @@ obj-$(CONFIG_OMAP_CF) += omap_cf.o
  221. obj-$(CONFIG_ELECTRA_CF) += electra_cf.o
  222. obj-$(CONFIG_PCMCIA_ALCHEMY_DEVBOARD) += db1xxx_ss.o
  223. obj-$(CONFIG_PCMCIA_MAX1600) += max1600.o
  224. +obj-$(CONFIG_PCMCIA_HD6446X_PCC) += hd6446x_pcc.o
  225. sa1111_cs-y += sa1111_generic.o
  226. sa1111_cs-$(CONFIG_ASSABET_NEPONSET) += sa1111_neponset.o
  227. diff --git a/drivers/pcmcia/hd6446x_pcc.c b/drivers/pcmcia/hd6446x_pcc.c
  228. new file mode 100644
  229. index 000000000000..31074f93b55b
  230. --- /dev/null
  231. +++ b/drivers/pcmcia/hd6446x_pcc.c
  232. @@ -0,0 +1,453 @@
  233. +// SPDX-License-Identifier: GPL-2.0
  234. +/*
  235. + * PC Card Controller driver for the Hitachi HD6446x series of Intelligent
  236. + * Peripheral Controllers.
  237. + *
  238. + * Copyright (c) 2023 - 2024 Artur Rojek <contact@artur-rojek.eu>
  239. + */
  240. +
  241. +#include <linux/clk.h>
  242. +#include <linux/interrupt.h>
  243. +#include <linux/of.h>
  244. +#include <linux/platform_device.h>
  245. +#include <pcmcia/hd6446x_pcc.h>
  246. +#include <pcmcia/ss.h>
  247. +#include <asm/hd64461.h>
  248. +
  249. +#include "mach-common/mach/hp6xx.h"
  250. +
  251. +#define HD6446X_PCC_ISR 0x00
  252. +#define HD6446X_PCC_GCR 0x02
  253. +#define HD6446X_PCC_CSCR 0x04
  254. +#define HD6446X_PCC_CSCIER 0x06
  255. +#define HD6446X_PCC_SCR 0x08
  256. +
  257. +#define HD6446X_PCC_ISR_CD (BIT(2) | BIT(3))
  258. +#define HD6446X_PCC_ISR_VS1 BIT(4)
  259. +#define HD6446X_PCC_ISR_VS2 BIT(5)
  260. +#define HD6446X_PCC_ISR_MWP BIT(6)
  261. +#define HD6446X_PCC_ISR_READY BIT(7)
  262. +
  263. +#define HD6446X_PCC_GCR_PMMOD BIT(3)
  264. +#define HD6446X_PCC_GCR_VCC0 BIT(4)
  265. +#define HD6446X_PCC_GCR_PCCT BIT(5)
  266. +#define HD6446X_PCC_GCR_PCCR BIT(6)
  267. +#define HD6446X_PCC_GCR_DRV BIT(7)
  268. +
  269. +#define HD6446X_PCC_CSCR_BD BIT(0)
  270. +#define HD6446X_PCC_CSCR_BW BIT(1)
  271. +#define HD6446X_PCC_CSCR_RC BIT(2)
  272. +#define HD6446X_PCC_CSCR_CDC BIT(3)
  273. +#define HD6446X_PCC_CSCR_SC BIT(4)
  274. +#define HD6446X_PCC_CSCR_IREQ BIT(5)
  275. +#define HD6446X_PCC_CSCR_SCDI BIT(7)
  276. +
  277. +#define HD6446X_PCC_CSCIER_BDE BIT(0)
  278. +#define HD6446X_PCC_CSCIER_BWE BIT(1)
  279. +#define HD6446X_PCC_CSCIER_RE BIT(2)
  280. +#define HD6446X_PCC_CSCIER_CDE BIT(3)
  281. +#define HD6446X_PCC_CSCIER_SCE BIT(4)
  282. +#define HD6446X_PCC_CSCIER_IREQE_FALLING BIT(6)
  283. +
  284. +#define HD6446X_PCC_SCR_VCC1 BIT(1)
  285. +
  286. +#define HD6446X_PCC_WINDOW 0x1000000 /* 16 MiB */
  287. +
  288. +struct hd6446x_pcc {
  289. + const struct hd6446x_pcc_plat_data *pdata;
  290. + void __iomem *reg;
  291. + void __iomem *base;
  292. + struct clk *clk;
  293. + struct pcmcia_socket socket;
  294. + struct socket_state_t state;
  295. + bool memory_card;
  296. +};
  297. +
  298. +static int hd64461_pcmcia_socket_set_voltage(struct hd6446x_pcc *pcc, int Vcc)
  299. +{
  300. + int gcr, scr, stbcr;
  301. +
  302. + gcr = readb(pcc->reg + HD6446X_PCC_GCR);
  303. + scr = readb(pcc->reg + HD6446X_PCC_SCR);
  304. +
  305. + switch (Vcc) {
  306. + case 0:
  307. + gcr |= HD6446X_PCC_GCR_VCC0;
  308. + scr |= HD6446X_PCC_SCR_VCC1;
  309. + break;
  310. + case 33:
  311. + gcr |= HD6446X_PCC_GCR_VCC0;
  312. + scr &= ~HD6446X_PCC_SCR_VCC1;
  313. + break;
  314. + case 50:
  315. + gcr &= ~HD6446X_PCC_GCR_VCC0;
  316. + scr &= ~HD6446X_PCC_SCR_VCC1;
  317. + break;
  318. + default:
  319. + printk("Unsupported voltage: %d\n", Vcc);
  320. + return -EINVAL;
  321. + }
  322. +
  323. + writeb(gcr, pcc->reg + HD6446X_PCC_GCR);
  324. + writeb(scr, pcc->reg + HD6446X_PCC_SCR);
  325. +
  326. +// stbcr = readw(HD64461_STBCR);
  327. +
  328. + if (Vcc > 0)
  329. + clk_enable(pcc->clk);
  330. +// stbcr &= ~HD64461_STBCR_SPC0ST;
  331. + else
  332. + clk_disable(pcc->clk);
  333. +// stbcr |= HD64461_STBCR_SPC0ST;
  334. +
  335. +// writew(stbcr, HD64461_STBCR);
  336. +
  337. + return 0;
  338. +}
  339. +
  340. +static int hd64461_pcmcia_socket_init(struct pcmcia_socket *sock)
  341. +{
  342. + struct hd6446x_pcc *pcc = sock->driver_data;
  343. + int reg;
  344. +
  345. + printk("socket_init\n");
  346. +
  347. +// printk("init BCR1: %04x\n", readw(0xffffff60));
  348. +
  349. + (void)hd64461_pcmcia_socket_set_voltage(pcc, 0);
  350. +
  351. + reg = readb(HD64461_GPADR);
  352. + reg &= ~HD64461_GPADR_PCMCIA0;
  353. + writeb(reg, HD64461_GPADR);
  354. +
  355. + return 0;
  356. +}
  357. +
  358. +static int hd64461_pcmcia_socket_get_status(struct pcmcia_socket *sock,
  359. + unsigned int *value)
  360. +{
  361. +// struct hd64461_pcmcia_socket *socket = sock->driver_data;
  362. + struct hd6446x_pcc *pcc = sock->driver_data;
  363. + unsigned int status = 0;
  364. + int reg;
  365. +
  366. + printk("get_status\n");
  367. +
  368. + reg = readb(pcc->reg + HD6446X_PCC_ISR);
  369. +
  370. +// printk("PCC0ISR: %02x\n", reg);
  371. +
  372. + if (reg & HD6446X_PCC_ISR_CD)
  373. + goto end; /* No card detected. */
  374. + status |= SS_DETECT;
  375. +
  376. + if (pcc->memory_card) {
  377. + if (reg & HD6446X_PCC_ISR_READY)
  378. + status |= SS_READY;
  379. +
  380. + if (reg & HD6446X_PCC_ISR_MWP)
  381. + status |= SS_WRPROT;
  382. + } else
  383. + status |= SS_STSCHG;
  384. +
  385. + if (!(reg & HD6446X_PCC_ISR_VS1)) {
  386. + status |= SS_3VCARD;
  387. + printk("3v3 card\n");
  388. + }
  389. +
  390. + if (!(reg & HD6446X_PCC_ISR_VS2)) {
  391. + status |= SS_XVCARD;
  392. + printk("X.Xv card\n");
  393. + }
  394. +
  395. + if (pcc->state.Vcc || pcc->state.Vpp)
  396. + status |= SS_POWERON;
  397. +
  398. +end:
  399. + *value = status;
  400. +// printk("status: %x, memory: %d\n", status, socket->memory_card);
  401. +
  402. + return 0;
  403. +}
  404. +
  405. +static int hd64461_pcmcia_socket_configure(struct pcmcia_socket *sock,
  406. + struct socket_state_t *state)
  407. +{
  408. +// struct hd64461_pcmcia_socket *socket = sock->driver_data;
  409. + struct hd6446x_pcc *pcc = sock->driver_data;
  410. + int reg = 0;
  411. +// unsigned long flags;
  412. +
  413. + writeb(0x0, pcc->reg + HD6446X_PCC_CSCIER);
  414. +
  415. +// local_irq_save(flags);
  416. +
  417. +// printk("socket_configure, flags: %x, csc_mask: %x, Vcc: %d, Vpp: %d, io_irq: %x\n",
  418. +// state->flags, state->csc_mask, state->Vcc, state->Vpp, state->io_irq);
  419. +
  420. + if (state->Vcc != pcc->state.Vcc || state->Vpp != pcc->state.Vpp)
  421. + if (hd64461_pcmcia_socket_set_voltage(pcc, state->Vcc)) {
  422. +// local_irq_restore(flags);
  423. + return -EINVAL;
  424. + }
  425. +
  426. + //reg = readb(HD64461_PCC0CSCIER) & HD64461_PCCCSCIER_IREQE_MASK;
  427. + reg = HD6446X_PCC_CSCIER_IREQE_FALLING;
  428. +// reg = 0;
  429. +
  430. + if (state->csc_mask & SS_DETECT)
  431. + reg |= HD6446X_PCC_CSCIER_CDE;
  432. + if (state->csc_mask & SS_READY)
  433. + reg |= HD6446X_PCC_CSCIER_RE;
  434. + if (state->csc_mask & SS_BATDEAD)
  435. + reg |= HD6446X_PCC_CSCIER_BDE;
  436. + if (state->csc_mask & SS_BATWARN)
  437. + reg |= HD6446X_PCC_CSCIER_BWE;
  438. + if (state->csc_mask & SS_STSCHG)
  439. + reg |= HD6446X_PCC_CSCIER_SCE;
  440. +// if (state->flags & SS_IOCARD)
  441. +// reg = HD64461_PCCCSCIER_IREQE_FALLING;
  442. +
  443. +
  444. + writeb(reg, pcc->reg + HD6446X_PCC_CSCIER);
  445. +
  446. +// reg = readb(HD64461_PCC0GCR);
  447. +// reg = 0;
  448. +// reg = HD6446X_PCC_GCR_PMMOD;
  449. + reg = readb(pcc->reg + HD6446X_PCC_GCR) & ~(HD6446X_PCC_GCR_PCCT |
  450. + HD6446X_PCC_GCR_PCCR |
  451. + HD6446X_PCC_GCR_DRV);
  452. +
  453. + pcc->memory_card = !(state->flags & SS_IOCARD);
  454. + if (!pcc->memory_card)
  455. + reg |= HD6446X_PCC_GCR_PCCT;
  456. + if (state->flags & SS_RESET)
  457. + reg |= HD6446X_PCC_GCR_PCCR;
  458. + if (state->flags & SS_OUTPUT_ENA)
  459. + reg |= HD6446X_PCC_GCR_DRV;
  460. +
  461. +#if 0
  462. + if (socket->memory_card)
  463. + reg &= ~HD64461_PCCGCR_PCCT;
  464. + else
  465. + reg |= HD64461_PCCGCR_PCCT;
  466. + if (state->flags & SS_RESET)
  467. + reg |= HD64461_PCCGCR_PCCR;
  468. + else
  469. + reg &= ~HD64461_PCCGCR_PCCR;
  470. + if (state->flags & SS_OUTPUT_ENA)
  471. + reg |= HD64461_PCCGCR_DRVE;
  472. + else
  473. + reg &= ~HD64461_PCCGCR_DRVE;
  474. +#endif
  475. +
  476. + writeb(reg, pcc->reg + HD6446X_PCC_GCR);
  477. +
  478. + pcc->state = *state;
  479. +
  480. +// local_irq_restore(flags);
  481. +
  482. +// printk("Configured: %x\n", state->flags);
  483. +// printk("config BCR1: %04x\n", readw(0xffffff60));
  484. +
  485. + return 0;
  486. +}
  487. +
  488. +static int hd6446x_pcc_set_io_map(struct pcmcia_socket *socket,
  489. + struct pccard_io_map *io)
  490. +{
  491. + /* We use a static map. */
  492. + printk("hd6446x_pcc_set_io_map\n");
  493. + return 0;
  494. +}
  495. +
  496. +static int hd64461_pcmcia_socket_set_mem_map(struct pcmcia_socket *sock,
  497. + struct pccard_mem_map *map)
  498. +{
  499. + struct hd6446x_pcc *pcc = sock->driver_data;
  500. +// printk("set_mem_map\n");
  501. +
  502. + if (map->map >= MAX_WIN)
  503. + return -EINVAL;
  504. +
  505. + map->static_start = (uintptr_t)pcc->base + map->card_start;
  506. +// map->static_start = HD64461_PCC0_BASE + map->card_start;
  507. +// map->static_start = 0x8000000 + map->card_start;
  508. +
  509. +// printk("map->flags %d: %x\n", map->map, map->flags);
  510. +
  511. + if (!(map->flags & MAP_ATTRIB))
  512. + map->static_start += HD6446X_PCC_WINDOW;
  513. +
  514. + return 0;
  515. +}
  516. +
  517. +static struct pccard_operations hd64461_pcmcia_socket_ops = {
  518. + .init = hd64461_pcmcia_socket_init,
  519. + .get_status = hd64461_pcmcia_socket_get_status,
  520. + .set_socket = hd64461_pcmcia_socket_configure,
  521. + .set_io_map = hd6446x_pcc_set_io_map,
  522. + .set_mem_map = hd64461_pcmcia_socket_set_mem_map,
  523. +};
  524. +
  525. +static irqreturn_t hd64461_pcmcia_socket_irq(int irq, void *data)
  526. +{
  527. + struct hd6446x_pcc *pcc = data;
  528. + int reg = readb(pcc->reg + HD6446X_PCC_CSCR) & ~HD6446X_PCC_CSCR_SCDI;
  529. + unsigned int events = 0;
  530. +
  531. + if (reg & HD6446X_PCC_CSCR_IREQ) {
  532. + reg &= ~HD6446X_PCC_CSCR_IREQ;
  533. + writeb(reg, pcc->reg + HD6446X_PCC_CSCR);
  534. +
  535. + return IRQ_NONE;
  536. + }
  537. +
  538. + if (reg & HD6446X_PCC_CSCR_CDC) {
  539. + reg &= ~HD6446X_PCC_CSCR_CDC;
  540. + events |= SS_DETECT;
  541. +
  542. + /* Card has been ejected. */
  543. + if (readb(pcc->reg + HD6446X_PCC_ISR) & HD6446X_PCC_ISR_CD)
  544. + reg &= ~(HD6446X_PCC_CSCR_RC | HD6446X_PCC_CSCR_BW |
  545. + HD6446X_PCC_CSCR_BD | HD6446X_PCC_CSCR_SC);
  546. + }
  547. +
  548. + if (pcc->memory_card) {
  549. + if (reg & HD6446X_PCC_CSCR_RC) {
  550. + reg &= ~HD6446X_PCC_CSCR_RC;
  551. + events |= SS_READY;
  552. + }
  553. +
  554. + if (reg & HD6446X_PCC_CSCR_BW) {
  555. + reg &= ~HD6446X_PCC_CSCR_BW;
  556. + events |= SS_BATWARN;
  557. + }
  558. +
  559. + if (reg & HD6446X_PCC_CSCR_BD) {
  560. + reg &= ~HD6446X_PCC_CSCR_BD;
  561. + events |= SS_BATDEAD;
  562. + }
  563. + } else if (reg & HD6446X_PCC_CSCR_SC) {
  564. + reg &= ~HD6446X_PCC_CSCR_SC;
  565. + events |= SS_STSCHG;
  566. + }
  567. +
  568. + writeb(reg, pcc->reg + HD6446X_PCC_CSCR);
  569. +
  570. + if (events)
  571. + pcmcia_parse_events(&pcc->socket, events);
  572. +
  573. +// writeb(reg, HD64461_PCC0CSCR);
  574. +
  575. + return IRQ_HANDLED;
  576. +}
  577. +
  578. +static int hd64461_pcmcia_socket_probe(struct platform_device *pdev)
  579. +{
  580. + struct hd6446x_pcc *pcc;
  581. + struct device *dev = &pdev->dev;
  582. + struct pcmcia_socket *sock;
  583. + int irq;
  584. + int reg, ret;
  585. +
  586. + printk("pcc probe\n");
  587. +
  588. +// pcc = dev.platform_data;
  589. +// socket = platform_get_drvdata(pdev);
  590. +
  591. + pcc = devm_kzalloc(dev, sizeof(*pcc), GFP_KERNEL);
  592. + if (!pcc)
  593. + return -ENOMEM;
  594. +
  595. + pcc->pdata = dev_get_platdata(dev);
  596. + if (!pcc->pdata) {
  597. + dev_err(dev, "Unable to get platform data\n");
  598. + return -EINVAL;
  599. + }
  600. +
  601. + pcc->memory_card = true;
  602. + irq = platform_get_irq(pdev, 0);
  603. +
  604. + pcc->reg = devm_platform_ioremap_resource(pdev, 0);
  605. + if (IS_ERR(pcc->reg)) {
  606. + return PTR_ERR(pcc->reg);
  607. + }
  608. +
  609. + pcc->base = devm_platform_ioremap_resource(pdev, 1);
  610. + if (IS_ERR(pcc->base)) {
  611. + return PTR_ERR(pcc->base);
  612. + }
  613. +
  614. +// pcc->reg = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  615. +// pcc->base = platform_get_resource(pdev, IORESOURCE_MEM, 1);
  616. +
  617. + sock = &pcc->socket;
  618. + sock->driver_data = pcc;
  619. + sock->resource_ops = &pccard_static_ops;
  620. + sock->ops = &hd64461_pcmcia_socket_ops;
  621. + sock->owner = THIS_MODULE;
  622. + sock->dev.parent = &pdev->dev;
  623. + sock->features = SS_CAP_STATIC_MAP | SS_CAP_PCCARD | SS_CAP_PAGE_REGS;
  624. + sock->pci_irq = irq;
  625. + sock->irq_mask = 0xffde;
  626. +
  627. + sock->map_size = HD6446X_PCC_WINDOW;
  628. + sock->io_offset = (uintptr_t)pcc->base + sock->map_size * 2;
  629. +// sock->io_offset = HD6446X_PCC_IO;
  630. +// sock->io_offset = 0x8000000 + HD64461_PCC_WINDOW * 2;
  631. +
  632. + printk("sh_io_port_base: %lx\n", sh_io_port_base);
  633. +
  634. + ret = pcmcia_register_socket(sock);
  635. + if (ret) {
  636. + dev_err(dev, "Unable to register socket\n");
  637. + return ret;
  638. + }
  639. +
  640. + /* Put the hardware in a known state. */
  641. +// printk("CSCIER: %x\n", readb(pcc->reg + HD6446X_PCC_CSCIER));
  642. + writeb(HD6446X_PCC_CSCIER_IREQE_FALLING | HD6446X_PCC_CSCIER_CDE,
  643. + pcc->reg + HD6446X_PCC_CSCIER);
  644. + writeb(0x0, pcc->reg + HD6446X_PCC_CSCR);
  645. + writeb(HD6446X_PCC_GCR_PMMOD | HD6446X_PCC_GCR_DRV, pcc->reg + HD6446X_PCC_GCR);
  646. +
  647. + ret = devm_request_irq(dev, irq, hd64461_pcmcia_socket_irq,
  648. + IRQF_SHARED, dev_name(dev), pcc);
  649. + if (ret < 0) {
  650. + dev_err(dev, "Failed to request irq: %d\n", ret);
  651. + return ret;
  652. + }
  653. +
  654. + pcc->clk = devm_clk_get_prepared(dev,
  655. + pcc->pdata->slot_id ? "pcc0" : "pcc1");
  656. + if (IS_ERR(pcc->clk)) {
  657. + dev_err(dev, "Unable to get clock\n");
  658. + return PTR_ERR(pcc->clk);
  659. + }
  660. +// clk_disable(pcc->clk);
  661. +
  662. + printk("reg: %lx, base: %lx, basep: %lx\n",
  663. + (uintptr_t)pcc->reg,
  664. + (uintptr_t)pcc->base,
  665. + virt_to_phys(pcc->base));
  666. +
  667. + return 0;
  668. +}
  669. +
  670. +static void hd64461_pcmcia_socket_remove(struct platform_device *pdev)
  671. +{
  672. + struct hd6446x_pcc *pcc = platform_get_drvdata(pdev);
  673. +
  674. + pcmcia_unregister_socket(&pcc->socket);
  675. +}
  676. +
  677. +static struct platform_driver hd64461_pcmcia_socket_driver = {
  678. + .driver = {
  679. + .name = "hd6446x_pcc",
  680. + },
  681. + .probe = hd64461_pcmcia_socket_probe,
  682. + .remove = hd64461_pcmcia_socket_remove,
  683. +};
  684. +
  685. +module_platform_driver(hd64461_pcmcia_socket_driver);
  686. diff --git a/include/pcmcia/hd6446x_pcc.h b/include/pcmcia/hd6446x_pcc.h
  687. new file mode 100644
  688. index 000000000000..d1fe98f0a701
  689. --- /dev/null
  690. +++ b/include/pcmcia/hd6446x_pcc.h
  691. @@ -0,0 +1,9 @@
  692. +#ifndef _HD6446X_PCC_
  693. +#define _HD6446X_PCC_
  694. +
  695. +struct hd6446x_pcc_plat_data {
  696. + int slot_id;
  697. + bool io_support;
  698. +};
  699. +
  700. +#endif /* _HD6446X_PCC_ */
  701. --
  702. 2.50.1