1*c924ee25SMaxime Ripard // SPDX-License-Identifier:	GPL-2.0+
2*c924ee25SMaxime Ripard /*
3*c924ee25SMaxime Ripard  *
4*c924ee25SMaxime Ripard  * Copyright (c) 2015 Free Electrons
5*c924ee25SMaxime Ripard  * Copyright (c) 2015 NextThing Co.
6*c924ee25SMaxime Ripard  * Copyright (c) 2018 Microchip Technology, Inc.
7*c924ee25SMaxime Ripard  *
8*c924ee25SMaxime Ripard  * Maxime Ripard <maxime.ripard@free-electrons.com>
9*c924ee25SMaxime Ripard  * Eugen Hristev <eugen.hristev@microchip.com>
10*c924ee25SMaxime Ripard  *
11*c924ee25SMaxime Ripard  */
12*c924ee25SMaxime Ripard 
13*c924ee25SMaxime Ripard #include <common.h>
14*c924ee25SMaxime Ripard #include <dm.h>
15*c924ee25SMaxime Ripard #include <w1.h>
16*c924ee25SMaxime Ripard #include <w1-eeprom.h>
17*c924ee25SMaxime Ripard 
18*c924ee25SMaxime Ripard #include <dm/device-internal.h>
19*c924ee25SMaxime Ripard 
w1_eeprom_read_buf(struct udevice * dev,unsigned int offset,u8 * buf,unsigned int count)20*c924ee25SMaxime Ripard int w1_eeprom_read_buf(struct udevice *dev, unsigned int offset,
21*c924ee25SMaxime Ripard 		       u8 *buf, unsigned int count)
22*c924ee25SMaxime Ripard {
23*c924ee25SMaxime Ripard 	const struct w1_eeprom_ops *ops = device_get_ops(dev);
24*c924ee25SMaxime Ripard 	u64 id = 0;
25*c924ee25SMaxime Ripard 	int ret;
26*c924ee25SMaxime Ripard 
27*c924ee25SMaxime Ripard 	if (!ops->read_buf)
28*c924ee25SMaxime Ripard 		return -ENOSYS;
29*c924ee25SMaxime Ripard 
30*c924ee25SMaxime Ripard 	ret = w1_eeprom_get_id(dev, &id);
31*c924ee25SMaxime Ripard 	if (ret)
32*c924ee25SMaxime Ripard 		return ret;
33*c924ee25SMaxime Ripard 	if (!id)
34*c924ee25SMaxime Ripard 		return -ENODEV;
35*c924ee25SMaxime Ripard 
36*c924ee25SMaxime Ripard 	return ops->read_buf(dev, offset, buf, count);
37*c924ee25SMaxime Ripard }
38*c924ee25SMaxime Ripard 
w1_eeprom_register_new_device(u64 id)39*c924ee25SMaxime Ripard int w1_eeprom_register_new_device(u64 id)
40*c924ee25SMaxime Ripard {
41*c924ee25SMaxime Ripard 	u8 family = id & 0xff;
42*c924ee25SMaxime Ripard 	int ret;
43*c924ee25SMaxime Ripard 	struct udevice *dev;
44*c924ee25SMaxime Ripard 
45*c924ee25SMaxime Ripard 	for (ret = uclass_first_device(UCLASS_W1_EEPROM, &dev);
46*c924ee25SMaxime Ripard 	     !ret && dev;
47*c924ee25SMaxime Ripard 	     uclass_next_device(&dev)) {
48*c924ee25SMaxime Ripard 		if (ret || !dev) {
49*c924ee25SMaxime Ripard 			debug("cannot find w1 eeprom dev\n");
50*c924ee25SMaxime Ripard 			return ret;
51*c924ee25SMaxime Ripard 		}
52*c924ee25SMaxime Ripard 		if (dev_get_driver_data(dev) == family) {
53*c924ee25SMaxime Ripard 			struct w1_device *w1;
54*c924ee25SMaxime Ripard 
55*c924ee25SMaxime Ripard 			w1 = dev_get_parent_platdata(dev);
56*c924ee25SMaxime Ripard 			if (w1->id) /* device already in use */
57*c924ee25SMaxime Ripard 				continue;
58*c924ee25SMaxime Ripard 			w1->id = id;
59*c924ee25SMaxime Ripard 			debug("%s: Match found: %s:%s %llx\n", __func__,
60*c924ee25SMaxime Ripard 			      dev->name, dev->driver->name, id);
61*c924ee25SMaxime Ripard 			return 0;
62*c924ee25SMaxime Ripard 		}
63*c924ee25SMaxime Ripard 	}
64*c924ee25SMaxime Ripard 
65*c924ee25SMaxime Ripard 	debug("%s: No matches found: error %d\n", __func__, ret);
66*c924ee25SMaxime Ripard 
67*c924ee25SMaxime Ripard 	return ret;
68*c924ee25SMaxime Ripard }
69*c924ee25SMaxime Ripard 
w1_eeprom_get_id(struct udevice * dev,u64 * id)70*c924ee25SMaxime Ripard int w1_eeprom_get_id(struct udevice *dev, u64 *id)
71*c924ee25SMaxime Ripard {
72*c924ee25SMaxime Ripard 	struct w1_device *w1 = dev_get_parent_platdata(dev);
73*c924ee25SMaxime Ripard 
74*c924ee25SMaxime Ripard 	if (!w1)
75*c924ee25SMaxime Ripard 		return -ENODEV;
76*c924ee25SMaxime Ripard 	*id = w1->id;
77*c924ee25SMaxime Ripard 
78*c924ee25SMaxime Ripard 	return 0;
79*c924ee25SMaxime Ripard }
80*c924ee25SMaxime Ripard 
81*c924ee25SMaxime Ripard UCLASS_DRIVER(w1_eeprom) = {
82*c924ee25SMaxime Ripard 	.name		= "w1_eeprom",
83*c924ee25SMaxime Ripard 	.id		= UCLASS_W1_EEPROM,
84*c924ee25SMaxime Ripard 	.flags		= DM_UC_FLAG_SEQ_ALIAS,
85*c924ee25SMaxime Ripard #if CONFIG_IS_ENABLED(OF_CONTROL)
86*c924ee25SMaxime Ripard 	.post_bind	= dm_scan_fdt_dev,
87*c924ee25SMaxime Ripard #endif
88*c924ee25SMaxime Ripard };
89*c924ee25SMaxime Ripard 
w1_eeprom_dm_init(void)90*c924ee25SMaxime Ripard int w1_eeprom_dm_init(void)
91*c924ee25SMaxime Ripard {
92*c924ee25SMaxime Ripard 	struct udevice *dev;
93*c924ee25SMaxime Ripard 	struct uclass *uc;
94*c924ee25SMaxime Ripard 	int ret;
95*c924ee25SMaxime Ripard 
96*c924ee25SMaxime Ripard 	ret = uclass_get(UCLASS_W1_EEPROM, &uc);
97*c924ee25SMaxime Ripard 	if (ret) {
98*c924ee25SMaxime Ripard 		debug("W1_EEPROM uclass not available\n");
99*c924ee25SMaxime Ripard 		return ret;
100*c924ee25SMaxime Ripard 	}
101*c924ee25SMaxime Ripard 
102*c924ee25SMaxime Ripard 	uclass_foreach_dev(dev, uc) {
103*c924ee25SMaxime Ripard 		ret = device_probe(dev);
104*c924ee25SMaxime Ripard 		if (ret == -ENODEV) {	/* No such device. */
105*c924ee25SMaxime Ripard 			debug("W1_EEPROM not available.\n");
106*c924ee25SMaxime Ripard 			continue;
107*c924ee25SMaxime Ripard 		}
108*c924ee25SMaxime Ripard 
109*c924ee25SMaxime Ripard 		if (ret) {		/* Other error. */
110*c924ee25SMaxime Ripard 			printf("W1_EEPROM probe failed, error %d\n", ret);
111*c924ee25SMaxime Ripard 			continue;
112*c924ee25SMaxime Ripard 		}
113*c924ee25SMaxime Ripard 	}
114*c924ee25SMaxime Ripard 
115*c924ee25SMaxime Ripard 	return 0;
116*c924ee25SMaxime Ripard }
117