1 // SPDX-License-Identifier: GPL-2.0+
3 * sl28 extension commands
5 * Copyright (c) 2020 Kontron Europe GmbH
11 #include <linux/delay.h>
13 #define CPLD_I2C_ADDR 0x4a
14 #define REG_UFM_CTRL 0x02
15 #define UFM_CTRL_DCLK BIT(1)
16 #define UFM_CTRL_DIN BIT(2)
17 #define UFM_CTRL_PROGRAM BIT(3)
18 #define UFM_CTRL_ERASE BIT(4)
19 #define UFM_CTRL_DSHIFT BIT(5)
20 #define UFM_CTRL_DOUT BIT(6)
21 #define UFM_CTRL_BUSY BIT(7)
23 static int ufm_shift_data(struct udevice *dev, u16 data_in, u16 *data_out)
30 ret = dm_i2c_reg_write(dev, REG_UFM_CTRL, 0);
33 ret = dm_i2c_reg_write(dev, REG_UFM_CTRL, UFM_CTRL_DCLK);
38 ret = dm_i2c_reg_write(dev, REG_UFM_CTRL,
39 UFM_CTRL_DSHIFT | UFM_CTRL_DCLK);
43 /* clock 16 data bits, reverse order */
44 for (i = 15; i >= 0; i--) {
45 u8 din = (data_in & (1 << i)) ? UFM_CTRL_DIN : 0;
47 ret = dm_i2c_reg_write(dev, REG_UFM_CTRL, UFM_CTRL_DSHIFT
52 ret = dm_i2c_reg_read(dev, REG_UFM_CTRL);
55 if (ret & UFM_CTRL_DOUT)
58 ret = dm_i2c_reg_write(dev, REG_UFM_CTRL,
59 UFM_CTRL_DSHIFT | UFM_CTRL_DCLK | din);
64 /* deassert drshift */
65 ret = dm_i2c_reg_write(dev, REG_UFM_CTRL, UFM_CTRL_DCLK);
75 static int ufm_erase(struct udevice *dev)
79 /* erase, tEPMX is 500ms */
80 ret = dm_i2c_reg_write(dev, REG_UFM_CTRL,
81 UFM_CTRL_DCLK | UFM_CTRL_ERASE);
84 ret = dm_i2c_reg_write(dev, REG_UFM_CTRL, UFM_CTRL_DCLK);
92 static int ufm_program(struct udevice *dev)
96 /* program, tPPMX is 100us */
97 ret = dm_i2c_reg_write(dev, REG_UFM_CTRL,
98 UFM_CTRL_DCLK | UFM_CTRL_PROGRAM);
101 ret = dm_i2c_reg_write(dev, REG_UFM_CTRL, UFM_CTRL_DCLK);
109 static int ufm_write(struct udevice *dev, u16 data)
113 ret = ufm_shift_data(dev, data, NULL);
117 ret = ufm_erase(dev);
121 return ufm_program(dev);
124 static int ufm_read(struct udevice *dev, u16 *data)
126 return ufm_shift_data(dev, 0, data);
129 static int do_sl28_nvm(struct cmd_tbl *cmdtp, int flag, int argc,
137 if (i2c_get_chip_for_busnum(0, CPLD_I2C_ADDR, 1, &dev))
138 return CMD_RET_FAILURE;
141 nvm = hextoul(argv[1], &endp);
143 printf("ERROR: argument is not a valid number\n");
149 * We swap all bits, because the a zero bit in hardware means the
150 * feature is enabled. But this is hard for the user.
154 ret = ufm_write(dev, nvm);
157 printf("New settings will be activated after the next power cycle!\n");
159 ret = ufm_read(dev, &nvm);
164 printf("%04hx\n", nvm);
167 return CMD_RET_SUCCESS;
170 printf("command failed (%d)\n", ret);
171 return CMD_RET_FAILURE;
174 static char sl28_help_text[] =
175 "nvm [<hex>] - display/set the 16 non-volatile bits\n";
177 U_BOOT_CMD_WITH_SUBCMDS(sl28, "SMARC-sAL28 specific", sl28_help_text,
178 U_BOOT_SUBCMD_MKENT(nvm, 2, 1, do_sl28_nvm));