2 * ULCB board CPLD access support
4 * Copyright (C) 2017 Renesas Electronics Corporation
5 * Copyright (C) 2017 Cogent Embedded, Inc.
7 * SPDX-License-Identifier: GPL-2.0+
15 #include <linux/err.h>
18 #define CPLD_ADDR_MODE 0x00 /* RW */
19 #define CPLD_ADDR_MUX 0x02 /* RW */
20 #define CPLD_ADDR_DIPSW6 0x08 /* R */
21 #define CPLD_ADDR_RESET 0x80 /* RW */
22 #define CPLD_ADDR_VERSION 0xFF /* R */
24 struct renesas_ulcb_sysreset_priv
{
25 struct gpio_desc miso
;
26 struct gpio_desc mosi
;
28 struct gpio_desc sstbz
;
31 static u32
cpld_read(struct udevice
*dev
, u8 addr
)
33 struct renesas_ulcb_sysreset_priv
*priv
= dev_get_priv(dev
);
37 for (i
= 0; i
< 8; i
++) {
38 dm_gpio_set_value(&priv
->mosi
, !!(addr
& 0x80)); /* MSB first */
39 dm_gpio_set_value(&priv
->sck
, 1);
41 dm_gpio_set_value(&priv
->sck
, 0);
44 dm_gpio_set_value(&priv
->mosi
, 0); /* READ */
45 dm_gpio_set_value(&priv
->sstbz
, 0);
46 dm_gpio_set_value(&priv
->sck
, 1);
47 dm_gpio_set_value(&priv
->sck
, 0);
48 dm_gpio_set_value(&priv
->sstbz
, 1);
50 for (i
= 0; i
< 32; i
++) {
51 dm_gpio_set_value(&priv
->sck
, 1);
53 data
|= dm_gpio_get_value(&priv
->miso
); /* MSB first */
54 dm_gpio_set_value(&priv
->sck
, 0);
60 static void cpld_write(struct udevice
*dev
, u8 addr
, u32 data
)
62 struct renesas_ulcb_sysreset_priv
*priv
= dev_get_priv(dev
);
65 for (i
= 0; i
< 32; i
++) {
66 dm_gpio_set_value(&priv
->mosi
, data
& (1 << 31)); /* MSB first */
67 dm_gpio_set_value(&priv
->sck
, 1);
69 dm_gpio_set_value(&priv
->sck
, 0);
72 for (i
= 0; i
< 8; i
++) {
73 dm_gpio_set_value(&priv
->mosi
, addr
& 0x80); /* MSB first */
74 dm_gpio_set_value(&priv
->sck
, 1);
76 dm_gpio_set_value(&priv
->sck
, 0);
79 dm_gpio_set_value(&priv
->mosi
, 1); /* WRITE */
80 dm_gpio_set_value(&priv
->sstbz
, 0);
81 dm_gpio_set_value(&priv
->sck
, 1);
82 dm_gpio_set_value(&priv
->sck
, 0);
83 dm_gpio_set_value(&priv
->sstbz
, 1);
86 static int do_cpld(cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[])
92 ret
= uclass_get_device_by_driver(UCLASS_SYSRESET
,
93 DM_GET_DRIVER(sysreset_renesas_ulcb
),
98 if (argc
== 2 && strcmp(argv
[1], "info") == 0) {
99 printf("CPLD version:\t\t\t0x%08x\n",
100 cpld_read(dev
, CPLD_ADDR_VERSION
));
101 printf("H3 Mode setting (MD0..28):\t0x%08x\n",
102 cpld_read(dev
, CPLD_ADDR_MODE
));
103 printf("Multiplexer settings:\t\t0x%08x\n",
104 cpld_read(dev
, CPLD_ADDR_MUX
));
105 printf("DIPSW (SW6):\t\t\t0x%08x\n",
106 cpld_read(dev
, CPLD_ADDR_DIPSW6
));
111 return CMD_RET_USAGE
;
113 addr
= simple_strtoul(argv
[2], NULL
, 16);
114 if (!(addr
== CPLD_ADDR_VERSION
|| addr
== CPLD_ADDR_MODE
||
115 addr
== CPLD_ADDR_MUX
|| addr
== CPLD_ADDR_DIPSW6
||
116 addr
== CPLD_ADDR_RESET
)) {
117 printf("Invalid CPLD register address\n");
118 return CMD_RET_USAGE
;
121 if (argc
== 3 && strcmp(argv
[1], "read") == 0) {
122 printf("0x%x\n", cpld_read(dev
, addr
));
123 } else if (argc
== 4 && strcmp(argv
[1], "write") == 0) {
124 val
= simple_strtoul(argv
[3], NULL
, 16);
125 cpld_write(dev
, addr
, val
);
136 "cpld write addr val\n"
139 static int renesas_ulcb_sysreset_request(struct udevice
*dev
, enum sysreset_t type
)
141 cpld_write(dev
, CPLD_ADDR_RESET
, 1);
146 static int renesas_ulcb_sysreset_probe(struct udevice
*dev
)
148 struct renesas_ulcb_sysreset_priv
*priv
= dev_get_priv(dev
);
150 if (gpio_request_by_name(dev
, "gpio-miso", 0, &priv
->miso
,
154 if (gpio_request_by_name(dev
, "gpio-sck", 0, &priv
->sck
,
158 if (gpio_request_by_name(dev
, "gpio-sstbz", 0, &priv
->sstbz
,
159 GPIOD_IS_OUT
| GPIOD_IS_OUT_ACTIVE
))
162 if (gpio_request_by_name(dev
, "gpio-mosi", 0, &priv
->mosi
,
166 /* PULL-UP on MISO line */
167 setbits_le32(PFC_PUEN5
, PUEN_SSI_SDATA4
);
170 cpld_read(dev
, CPLD_ADDR_VERSION
);
175 static struct sysreset_ops renesas_ulcb_sysreset
= {
176 .request
= renesas_ulcb_sysreset_request
,
179 static const struct udevice_id renesas_ulcb_sysreset_ids
[] = {
180 { .compatible
= "renesas,ulcb-cpld" },
184 U_BOOT_DRIVER(sysreset_renesas_ulcb
) = {
185 .name
= "renesas_ulcb_sysreset",
186 .id
= UCLASS_SYSRESET
,
187 .ops
= &renesas_ulcb_sysreset
,
188 .probe
= renesas_ulcb_sysreset_probe
,
189 .of_match
= renesas_ulcb_sysreset_ids
,
190 .priv_auto_alloc_size
= sizeof(struct renesas_ulcb_sysreset_priv
),