1 // SPDX-License-Identifier: GPL-2.0+
2 /* (C) Copyright 2019 CompuLab, Ltd. <www.compulab.co.il> */
3 
4 #include <common.h>
5 #include <i2c.h>
6 #include <linux/kernel.h>
7 #include <asm/arch/imx8mq_pins.h>
8 #include <asm/mach-imx/gpio.h>
9 #include <asm-generic/gpio.h>
10 #include <asm/setup.h>
11 #include <linux/delay.h>
12 
13 #ifdef CONFIG_SPL_BUILD
14 
15 #define CFG_SYS_I2C_EEPROM_ADDR_P1	0x51
16 
17 static iomux_v3_cfg_t const eeprom_pads[] = {
18 	IMX8MQ_PAD_GPIO1_IO13__GPIO1_IO13 | MUX_PAD_CTRL(NO_PAD_CTRL),
19 };
20 
21 #define EEPROM_WP_GPIO IMX_GPIO_NR(1, 13)
22 
cl_eeprom_we(int enable)23 static void cl_eeprom_we(int enable)
24 {
25 	static int done;
26 
27 	if (done) {
28 		gpio_direction_output(EEPROM_WP_GPIO, enable);
29 		return;
30 	}
31 
32 	imx_iomux_v3_setup_multiple_pads(eeprom_pads, ARRAY_SIZE(eeprom_pads));
33 	gpio_request(EEPROM_WP_GPIO, "eeprom_wp");
34 	gpio_direction_output(EEPROM_WP_GPIO, enable);
35 	done = 1;
36 }
37 
cl_eeprom_read(uint offset,uchar * buf,int len)38 static int cl_eeprom_read(uint offset, uchar *buf, int len)
39 {
40 	struct udevice *dev;
41 	int ret;
42 
43 	ret = i2c_get_chip_for_busnum(1, CFG_SYS_I2C_EEPROM_ADDR_P1,
44 				      CONFIG_SYS_I2C_EEPROM_ADDR_LEN, &dev);
45 	if (ret) {
46 		printf("%s: Cannot find EEPROM: %d\n", __func__, ret);
47 		return ret;
48 	}
49 
50 	return dm_i2c_read(dev, offset, buf, len);
51 }
52 
cl_eeprom_write(uint offset,uchar * buf,int len)53 static int cl_eeprom_write(uint offset, uchar *buf, int len)
54 {
55 	struct udevice *dev;
56 	int ret;
57 
58 	cl_eeprom_we(1);
59 
60 	ret = i2c_get_chip_for_busnum(1, CFG_SYS_I2C_EEPROM_ADDR_P1,
61 				      CONFIG_SYS_I2C_EEPROM_ADDR_LEN, &dev);
62 	if (ret) {
63 		printf("%s: Cannot find EEPROM: %d\n", __func__, ret);
64 		return ret;
65 	}
66 
67 	return dm_i2c_write(dev, offset, buf, len);
68 }
69 
70 /* Reserved for fututre use area */
71 #define BOARD_DDRINFO_OFFSET 0x40
72 #define BOARD_DDR_SIZE 4
73 static u32 board_ddrinfo = 0xdeadbeef;
74 
75 #define BOARD_DDRSUBIND_OFFSET 0x44
76 #define BOARD_DDRSUBIND_SIZE 1
77 static u8 board_ddrsubind = 0xff;
78 
79 #define BOARD_OSIZE_OFFSET 0x80
80 #define BOARD_OSIZE_SIZE 4
81 static u32 board_osize = 0xdeadbeef;
82 
83 #define BOARD_DDRINFO_VALID(A) ((A) != 0xdeadbeef)
84 
cl_eeprom_get_ddrinfo(void)85 u32 cl_eeprom_get_ddrinfo(void)
86 {
87 	if (!BOARD_DDRINFO_VALID(board_ddrinfo)) {
88 		if (cl_eeprom_read(BOARD_DDRINFO_OFFSET, (uchar *)&board_ddrinfo, BOARD_DDR_SIZE))
89 			return 0;
90 	}
91 	return board_ddrinfo;
92 };
93 
cl_eeprom_set_ddrinfo(u32 ddrinfo)94 u32 cl_eeprom_set_ddrinfo(u32 ddrinfo)
95 {
96 	if (cl_eeprom_write(BOARD_DDRINFO_OFFSET, (uchar *)&ddrinfo, BOARD_DDR_SIZE))
97 		return 0;
98 
99 	board_ddrinfo = ddrinfo;
100 
101 	return board_ddrinfo;
102 };
103 
cl_eeprom_get_subind(void)104 u8 cl_eeprom_get_subind(void)
105 {
106 	if (cl_eeprom_read(BOARD_DDRSUBIND_OFFSET, (uchar *)&board_ddrsubind, BOARD_DDRSUBIND_SIZE))
107 		return 0xff;
108 
109 	return board_ddrsubind;
110 };
111 
cl_eeprom_set_subind(u8 ddrsubind)112 u8 cl_eeprom_set_subind(u8 ddrsubind)
113 {
114 	if (cl_eeprom_write(BOARD_DDRSUBIND_OFFSET, (uchar *)&ddrsubind, BOARD_DDRSUBIND_SIZE))
115 		return 0xff;
116 	board_ddrsubind = ddrsubind;
117 
118 	return board_ddrsubind;
119 };
120 
121 /* override-size ifaces */
cl_eeprom_get_osize(void)122 u32 cl_eeprom_get_osize(void)
123 {
124 	if (cl_eeprom_read(BOARD_OSIZE_OFFSET, (uchar *)&board_osize, BOARD_OSIZE_SIZE))
125 		return 0;
126 
127 	return board_osize;
128 };
129 #endif
130