2 * ulpi.c - USB ULPI PHY bus
4 * Copyright (C) 2015 Intel Corporation
6 * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
13 #include <linux/ulpi/interface.h>
14 #include <linux/ulpi/driver.h>
15 #include <linux/ulpi/regs.h>
16 #include <linux/module.h>
17 #include <linux/slab.h>
18 #include <linux/acpi.h>
20 /* -------------------------------------------------------------------------- */
22 int ulpi_read(struct ulpi
*ulpi
, u8 addr
)
24 return ulpi
->ops
->read(ulpi
->ops
, addr
);
26 EXPORT_SYMBOL_GPL(ulpi_read
);
28 int ulpi_write(struct ulpi
*ulpi
, u8 addr
, u8 val
)
30 return ulpi
->ops
->write(ulpi
->ops
, addr
, val
);
32 EXPORT_SYMBOL_GPL(ulpi_write
);
34 /* -------------------------------------------------------------------------- */
36 static int ulpi_match(struct device
*dev
, struct device_driver
*driver
)
38 struct ulpi_driver
*drv
= to_ulpi_driver(driver
);
39 struct ulpi
*ulpi
= to_ulpi_dev(dev
);
40 const struct ulpi_device_id
*id
;
42 for (id
= drv
->id_table
; id
->vendor
; id
++)
43 if (id
->vendor
== ulpi
->id
.vendor
&&
44 id
->product
== ulpi
->id
.product
)
50 static int ulpi_uevent(struct device
*dev
, struct kobj_uevent_env
*env
)
52 struct ulpi
*ulpi
= to_ulpi_dev(dev
);
54 if (add_uevent_var(env
, "MODALIAS=ulpi:v%04xp%04x",
55 ulpi
->id
.vendor
, ulpi
->id
.product
))
60 static int ulpi_probe(struct device
*dev
)
62 struct ulpi_driver
*drv
= to_ulpi_driver(dev
->driver
);
64 return drv
->probe(to_ulpi_dev(dev
));
67 static int ulpi_remove(struct device
*dev
)
69 struct ulpi_driver
*drv
= to_ulpi_driver(dev
->driver
);
72 drv
->remove(to_ulpi_dev(dev
));
77 static struct bus_type ulpi_bus
= {
80 .uevent
= ulpi_uevent
,
82 .remove
= ulpi_remove
,
85 /* -------------------------------------------------------------------------- */
87 static ssize_t
modalias_show(struct device
*dev
, struct device_attribute
*attr
,
90 struct ulpi
*ulpi
= to_ulpi_dev(dev
);
92 return sprintf(buf
, "ulpi:v%04xp%04x\n",
93 ulpi
->id
.vendor
, ulpi
->id
.product
);
95 static DEVICE_ATTR_RO(modalias
);
97 static struct attribute
*ulpi_dev_attrs
[] = {
98 &dev_attr_modalias
.attr
,
102 static struct attribute_group ulpi_dev_attr_group
= {
103 .attrs
= ulpi_dev_attrs
,
106 static const struct attribute_group
*ulpi_dev_attr_groups
[] = {
107 &ulpi_dev_attr_group
,
111 static void ulpi_dev_release(struct device
*dev
)
113 kfree(to_ulpi_dev(dev
));
116 static struct device_type ulpi_dev_type
= {
117 .name
= "ulpi_device",
118 .groups
= ulpi_dev_attr_groups
,
119 .release
= ulpi_dev_release
,
122 /* -------------------------------------------------------------------------- */
125 * ulpi_register_driver - register a driver with the ULPI bus
126 * @drv: driver being registered
128 * Registers a driver with the ULPI bus.
130 int ulpi_register_driver(struct ulpi_driver
*drv
)
135 drv
->driver
.bus
= &ulpi_bus
;
137 return driver_register(&drv
->driver
);
139 EXPORT_SYMBOL_GPL(ulpi_register_driver
);
142 * ulpi_unregister_driver - unregister a driver with the ULPI bus
143 * @drv: driver to unregister
145 * Unregisters a driver with the ULPI bus.
147 void ulpi_unregister_driver(struct ulpi_driver
*drv
)
149 driver_unregister(&drv
->driver
);
151 EXPORT_SYMBOL_GPL(ulpi_unregister_driver
);
153 /* -------------------------------------------------------------------------- */
155 static int ulpi_register(struct device
*dev
, struct ulpi
*ulpi
)
159 /* Test the interface */
160 ret
= ulpi_write(ulpi
, ULPI_SCRATCH
, 0xaa);
164 ret
= ulpi_read(ulpi
, ULPI_SCRATCH
);
171 ulpi
->id
.vendor
= ulpi_read(ulpi
, ULPI_VENDOR_ID_LOW
);
172 ulpi
->id
.vendor
|= ulpi_read(ulpi
, ULPI_VENDOR_ID_HIGH
) << 8;
174 ulpi
->id
.product
= ulpi_read(ulpi
, ULPI_PRODUCT_ID_LOW
);
175 ulpi
->id
.product
|= ulpi_read(ulpi
, ULPI_PRODUCT_ID_HIGH
) << 8;
177 ulpi
->dev
.parent
= dev
;
178 ulpi
->dev
.bus
= &ulpi_bus
;
179 ulpi
->dev
.type
= &ulpi_dev_type
;
180 dev_set_name(&ulpi
->dev
, "%s.ulpi", dev_name(dev
));
182 ACPI_COMPANION_SET(&ulpi
->dev
, ACPI_COMPANION(dev
));
184 request_module("ulpi:v%04xp%04x", ulpi
->id
.vendor
, ulpi
->id
.product
);
186 ret
= device_register(&ulpi
->dev
);
190 dev_dbg(&ulpi
->dev
, "registered ULPI PHY: vendor %04x, product %04x\n",
191 ulpi
->id
.vendor
, ulpi
->id
.product
);
197 * ulpi_register_interface - instantiate new ULPI device
198 * @dev: USB controller's device interface
199 * @ops: ULPI register access
201 * Allocates and registers a ULPI device and an interface for it. Called from
202 * the USB controller that provides the ULPI interface.
204 struct ulpi
*ulpi_register_interface(struct device
*dev
, struct ulpi_ops
*ops
)
209 ulpi
= kzalloc(sizeof(*ulpi
), GFP_KERNEL
);
211 return ERR_PTR(-ENOMEM
);
216 ret
= ulpi_register(dev
, ulpi
);
224 EXPORT_SYMBOL_GPL(ulpi_register_interface
);
227 * ulpi_unregister_interface - unregister ULPI interface
228 * @intrf: struct ulpi_interface
230 * Unregisters a ULPI device and it's interface that was created with
231 * ulpi_create_interface().
233 void ulpi_unregister_interface(struct ulpi
*ulpi
)
235 device_unregister(&ulpi
->dev
);
237 EXPORT_SYMBOL_GPL(ulpi_unregister_interface
);
239 /* -------------------------------------------------------------------------- */
241 static int __init
ulpi_init(void)
243 return bus_register(&ulpi_bus
);
245 subsys_initcall(ulpi_init
);
247 static void __exit
ulpi_exit(void)
249 bus_unregister(&ulpi_bus
);
251 module_exit(ulpi_exit
);
253 MODULE_AUTHOR("Intel Corporation");
254 MODULE_LICENSE("GPL v2");
255 MODULE_DESCRIPTION("USB ULPI PHY bus");