1
0
Fork 0

otgcontrol: implement initial FSM

Complete disabling of authenticated USB device connection in all modes

Code cleanup
- Spaces -> tabs
- Cleaner initiation sequence
pull/10/head
Steinar Bakkemo 2020-10-08 19:46:24 +02:00
parent e05abcf7da
commit 2833df5aa4
10 changed files with 1526 additions and 740 deletions

View File

@ -6,41 +6,60 @@
int otgcontrol_change_otg_charge_mode(struct rm_otgcontrol_data *otgc_data, int mode)
{
union power_supply_propval property_val;
int ret;
union power_supply_propval property_val;
printk("%s: Enter\n", __func__);
printk("%s: Enter\n", __func__);
switch(mode)
{
case OTG1_CHARGERMODE_CHARGE:
printk("%s: Setting OTG1 chargermode (CHARGE)\n", __func__);
property_val.intval = POWER_SUPPLY_MODE_CHARGER;
power_supply_set_property(otgc_data->pdata->vbus_supply,
POWER_SUPPLY_PROP_CHARGER_MODE,
&property_val);
property_val.intval = 1;
power_supply_set_property(otgc_data->pdata->vbus_supply,
POWER_SUPPLY_PROP_ONLINE,
&property_val);
break;
switch(mode)
{
case OTG1_CHARGERMODE_CHARGE:
printk("%s: Setting OTG1 chargermode (CHARGE)\n", __func__);
property_val.intval = POWER_SUPPLY_MODE_CHARGER;
ret = power_supply_set_property(otgc_data->pdata->vbus_supply,
POWER_SUPPLY_PROP_CHARGER_MODE,
&property_val);
if (ret < 0) {
printk("%s: Failed to set charger mode\n", __func__);
return ret;
}
case OTG1_CHARGERMODE_OTG:
printk("%s: Setting OTG1 chargermode (OTG)\n", __func__);
property_val.intval = POWER_SUPPLY_MODE_OTG_SUPPLY;
power_supply_set_property(otgc_data->pdata->vbus_supply,
POWER_SUPPLY_PROP_CHARGER_MODE,
&property_val);
property_val.intval = 1;
power_supply_set_property(otgc_data->pdata->vbus_supply,
POWER_SUPPLY_PROP_ONLINE,
&property_val);
break;
property_val.intval = 1;
ret = power_supply_set_property(otgc_data->pdata->vbus_supply,
POWER_SUPPLY_PROP_ONLINE,
&property_val);
if (ret < 0) {
printk("%s: Failed to enable charging after changing charger mode\n", __func__);
return ret;
}
break;
default:
printk("%s: Unable to set OTG1 chargermode (invalid mode %d)", __func__, mode);
return -EINVAL;
}
case OTG1_CHARGERMODE_OTG:
printk("%s: Setting OTG1 chargermode (OTG)\n", __func__);
property_val.intval = POWER_SUPPLY_MODE_OTG_SUPPLY;
ret = power_supply_set_property(otgc_data->pdata->vbus_supply,
POWER_SUPPLY_PROP_CHARGER_MODE,
&property_val);
if (ret < 0) {
printk("%s: Failed to set charger mode\n", __func__);
return ret;
}
otgc_data->otg1_chargermode = mode;
return 0;
property_val.intval = 1;
ret = power_supply_set_property(otgc_data->pdata->vbus_supply,
POWER_SUPPLY_PROP_ONLINE,
&property_val);
if (ret < 0) {
printk("%s: Failed to enable charging after changing charger mode\n", __func__);
return ret;
}
break;
default:
printk("%s: Unable to set OTG1 chargermode (invalid mode %d)", __func__, mode);
return -EINVAL;
}
otgc_data->otg1_chargermode = mode;
return 0;
}

View File

@ -3,9 +3,10 @@
#include <linux/rm-otgcontrol.h>
#define OTG1_CHARGERMODE_CHARGE 0
#define OTG1_CHARGERMODE_OTG 1
#define OTG1_CHARGERMODE_CHARGE 0
#define OTG1_CHARGERMODE_OTG 1
int otgcontrol_change_otg_charge_mode(struct rm_otgcontrol_data *otgc_data, int mode);
int otgcontrol_change_otg_charge_mode(struct rm_otgcontrol_data *otgc_data,
int mode);
#endif /* __OTGCONTROL_CHARGING_CTRL_H__ */

View File

@ -4,66 +4,66 @@
#include <linux/slab.h>
static const unsigned int usb_extcon_cable[] = {
EXTCON_USB_HOST,
EXTCON_NONE,
EXTCON_USB_HOST,
EXTCON_NONE,
};
int otgcontrol_init_extcon(struct rm_otgcontrol_data *otgc_data)
{
int ret;
int ret;
printk("%s: Allocating extcon device\n", __func__);
otgc_data->extcon_dev = devm_extcon_dev_allocate(otgc_data->dev, usb_extcon_cable);
if (IS_ERR(otgc_data->extcon_dev)) {
dev_err(otgc_data->dev, "%s: failed to allocate extcon device\n", __func__);
return -ENOMEM;
}
printk("%s: Allocating extcon device\n", __func__);
otgc_data->extcon_dev = devm_extcon_dev_allocate(otgc_data->dev, usb_extcon_cable);
if (IS_ERR(otgc_data->extcon_dev)) {
dev_err(otgc_data->dev, "%s: failed to allocate extcon device\n", __func__);
return -ENOMEM;
}
printk("%s: Registering extcon device\n", __func__);
ret = devm_extcon_dev_register(otgc_data->dev, otgc_data->extcon_dev);
if (ret < 0) {
dev_err(otgc_data->dev, "%s: Failed to register extcon device\n", __func__);
printk("%s: De-allocating extcon device\n", __func__);
kfree(otgc_data->extcon_dev);
otgc_data->extcon_dev = NULL;
return ret;
}
printk("%s: Registering extcon device\n", __func__);
ret = devm_extcon_dev_register(otgc_data->dev, otgc_data->extcon_dev);
if (ret < 0) {
dev_err(otgc_data->dev, "%s: Failed to register extcon device\n", __func__);
printk("%s: De-allocating extcon device\n", __func__);
kfree(otgc_data->extcon_dev);
otgc_data->extcon_dev = NULL;
return ret;
}
return 0;
return 0;
}
void otgcontrol_uninit_extcon(struct rm_otgcontrol_data *otgc_data)
{
if ((otgc_data->extcon_dev != NULL) && !IS_ERR(otgc_data->extcon_dev)) {
devm_extcon_dev_unregister(otgc_data->dev, otgc_data->extcon_dev);
kfree(otgc_data->extcon_dev);
otgc_data->extcon_dev = NULL;
}
if ((otgc_data->extcon_dev != NULL) && !IS_ERR(otgc_data->extcon_dev)) {
devm_extcon_dev_unregister(otgc_data->dev, otgc_data->extcon_dev);
kfree(otgc_data->extcon_dev);
otgc_data->extcon_dev = NULL;
}
}
int otgcontrol_set_dr_mode(struct rm_otgcontrol_data *otgc_data, int mode)
{
switch(mode)
{
case OTG1_DR_MODE__DEVICE:
printk("%s: Switching OTG1 DR mode -> DEVICE\n", __func__);
return extcon_set_state_sync(otgc_data->extcon_dev, EXTCON_USB_HOST, false);
break;
switch(mode)
{
case OTG1_DR_MODE__DEVICE:
printk("%s: Switching OTG1 DR mode -> DEVICE\n", __func__);
return extcon_set_state_sync(otgc_data->extcon_dev, EXTCON_USB_HOST, false);
break;
case OTG1_DR_MODE__HOST:
printk("%s: Switching OTG1 DR mode -> HOST\n", __func__);
return extcon_set_state_sync(otgc_data->extcon_dev, EXTCON_USB_HOST, true);
break;
case OTG1_DR_MODE__HOST:
printk("%s: Switching OTG1 DR mode -> HOST\n", __func__);
return extcon_set_state_sync(otgc_data->extcon_dev, EXTCON_USB_HOST, true);
break;
default:
printk("%s: unable to switch OTG1 DR mode (unknown mode %d)\n", __func__, mode);
return -EINVAL;
}
return 0;
default:
printk("%s: unable to switch OTG1 DR mode (unknown mode %d)\n", __func__, mode);
return -EINVAL;
}
return 0;
}
int otgcontrol_get_dr_mode(struct rm_otgcontrol_data *otgc_data)
{
/* Just return the last stored value */
return otgc_data->otg1_dr_mode;
/* Just return the last stored value */
return otgc_data->otg1_dr_mode;
}

File diff suppressed because it is too large Load Diff

View File

@ -4,29 +4,30 @@
#include <linux/rm-otgcontrol.h>
int otgcontrol_init_fsm(struct rm_otgcontrol_data *otgc_data);
int otgcontrol_set_controlmode(struct rm_otgcontrol_data *otgc_data, int mode);
int otgcontrol_handleInput(struct rm_otgcontrol_data *otgc_data, int signal, void *param);
static int otgcontrol_start_onewire_authentication(struct rm_otgcontrol_data *otgc_data);
#define OTG_MODE__MANUAL_CONTROL 0
#define OTG_MODE__ONEWIRE_AUTH 1
#define OTG_MODE__USB_NO_AUTH 2
#define OTG_MODE__MANUAL_CONTROL 0
#define OTG_MODE__ONEWIRE_AUTH 1
#define OTG_MODE__USB_NO_AUTH 2
#define OTG1_STATE__MANUAL_CONTROL 0
#define OTG1_STATE__ONEWIRE_AUTH_NOT_CONNECTED 1
#define OTG1_STATE__ONEWIRE_AUTH_WAIT_HANDSHAKE_RESPONS 2
#define OTG1_STATE__ONEWIRE_AUTH_DEVICE_CONNECTED 3
#define OTG1_STATE__USB_NO_AUTH_WAITING_CHALLENGE_RESPONSE 4
#define OTG1_STATE__USB_NO_AUTH_NOT_CONNECTED 5
#define OTG1_STATE__USB_NO_AUTH_DEVICE_CONNECTED 6
#define OTG1_STATE__HOST_CONNECTED 7
#define OTG1_STATE__MANUAL_CONTROL 0
#define OTG1_STATE__ONEWIRE_NOT_CONNECTED 1
#define OTG1_STATE__ONEWIRE_WAIT_HANDSHAKE_RESPONS 2
#define OTG1_STATE__ONEWIRE_DEVICE_CONNECTED 3
#define OTG1_STATE__USB_NOT_CONNECTED 4
#define OTG1_STATE__USB_DEVICE_CONNECTED 5
#define OTG1_STATE__HOST_CONNECTED 6
#define OTG1_EVENT__VBUS_CHANGED 0
#define OTG1_EVENT__ONEWIRE_GPIO_STATE_CHANGED 1
#define OTG1_EVENT__CHALLENGE_REPLY_RECEIVED 2
#define OTG1_EVENT__TIMEOUT 3
#define OTG1_EVENT__MODE_CHANGE_REQUESTED 4
#define OTG1_EVENT__OTG_CHARGERMODE_CHANGE_REQUESTED 5
#define OTG1_STATE__OTG_ID_STATE_CHANGE_REQUESTED 6
#define OTG1_EVENT__CHARGER_CONNECTED 0
#define OTG1_EVENT__CHARGER_DISCONNECTED 1
#define OTG1_EVENT__DEVICE_CONNECTED 2
#define OTG1_EVENT__DEVICE_DISCONNECTED 3
#define OTG1_EVENT__CHALLENGE_REPLY_RECEIVED 4
#define OTG1_EVENT__TIMEOUT 5
#define OTG1_EVENT__MODE_CHANGE_REQUESTED 6
#define OTG1_EVENT__MODE_CHANGE_CHALLENGE_REPLY 7
#define OTG1_EVENT__OTG_CHARGERMODE_CHANGE_REQUESTED 8
#define OTG1_EVENT__OTG_DR_MODE_CHANGE_REQUESTED 9
#endif /* __OTGCONTROL_FSM_H__ */

View File

@ -48,207 +48,207 @@
static int rm_otgcontrol_init(struct rm_otgcontrol_data *otgc_data)
{
int ret = 0;
int ret = 0;
printk("%s: Initiating sysfs nodes\n", __func__);
ret = otgcontrol_init_sysfs_nodes(otgc_data);
if (ret < 0)
return ret;
printk("%s: Initiating sysfs nodes\n", __func__);
ret = otgcontrol_init_sysfs_nodes(otgc_data);
if (ret < 0)
return ret;
printk("%s: Initiating default ONEWIRE_AUTH state\n", __func__);
ret = otgcontrol_init_fsm(otgc_data);
if (ret < 0)
return ret;
printk("%s: Initiating extcon device to control USB OTG dr mode\n", __func__);
ret = otgcontrol_init_extcon(otgc_data);
if (ret < 0) {
printk("%s: Failed to initiate extron (%d)\n", __func__, ret);
return ret;
}
printk("%s: Initiating extcon device to control USB OTG dr mode\n", __func__);
ret = otgcontrol_init_extcon(otgc_data);
if (ret < 0) {
printk("%s: Failed to initiate extron (%d)\n", __func__, ret);
return ret;
}
printk("%s: Initiating onewire state and setting to default state (GPIO)\n", __func__);
ret = otgcontrol_init_one_wire_mux_state(otgc_data);
if (ret < 0) {
printk("%s: Failed to initiate onewire pincontrol configuration\n", __func__);
return ret;
}
printk("%s: Initiating one-wire gpio irq\n", __func__);
ret = otgcontrol_init_gpio_irq(otgc_data);
return ret;
printk("%s: Initiating one-wire gpio irq\n", __func__);
ret = otgcontrol_init_gpio_irq(otgc_data);
if (ret < 0)
return ret;
printk("%s: Initiating fsm to start in AUTHORIZED MODE !!\n", __func__);
ret = otgcontrol_init_fsm(otgc_data);
return ret;
}
#ifdef CONFIG_OF
static int rm_otgcontrol_parse_dt(struct rm_otgcontrol_data *otgc_data)
{
struct device *dev = otgc_data->dev;
struct device_node *np = dev->of_node;
struct rm_otgcontrol_platform_data *pdata = otgc_data->pdata;
const char *vbus_supply_name;
int ret = 0, gpio_num;
struct device *dev = otgc_data->dev;
struct device_node *np = dev->of_node;
struct rm_otgcontrol_platform_data *pdata = otgc_data->pdata;
const char *vbus_supply_name;
int ret = 0;
printk("[---- SBA ----] %s: Enter\n", __func__);
printk("[---- SBA ----] %s: Enter\n", __func__);
if (of_find_property(np, "vbus-supply-name", NULL)) {
printk("[---- SBA ----] %s: Found vbus-supply-name property, trying to read it\n", __func__);
ret = of_property_read_string(np, "vbus-supply-name", &vbus_supply_name);
if (ret) {
printk("[---- SBA ----] %s: Failed to read property vbus-supply-name (code %d)\n", __func__, ret);
return ret;
}
if (of_find_property(np, "vbus-supply-name", NULL)) {
printk("[---- SBA ----] %s: Found vbus-supply-name property, trying to read it\n", __func__);
ret = of_property_read_string(np, "vbus-supply-name", &vbus_supply_name);
if (ret) {
printk("[---- SBA ----] %s: Failed to read property vbus-supply-name (code %d)\n", __func__, ret);
return ret;
}
printk("[---- SBA ----] %s: Read vbus-supply-name: %s, trying to get reference to it\n", __func__, vbus_supply_name);
pdata->vbus_supply = power_supply_get_by_name(vbus_supply_name);
if (IS_ERR(pdata->vbus_supply)) {
dev_err(dev, "%s: Failed to get supply '%s'\n", __func__, vbus_supply_name);
return PTR_ERR(pdata->vbus_supply);
}
printk("[---- SBA ----] %s: Read vbus-supply-name: %s, trying to get reference to it\n", __func__, vbus_supply_name);
pdata->vbus_supply = power_supply_get_by_name(vbus_supply_name);
if (IS_ERR(pdata->vbus_supply)) {
dev_err(dev, "%s: Failed to get supply '%s'\n", __func__, vbus_supply_name);
return PTR_ERR(pdata->vbus_supply);
}
if (!pdata->vbus_supply) {
printk("[---- SBA ----] %s: vbus supply not ready, defering probe\n", __func__);
return -EPROBE_DEFER;
}
if (!pdata->vbus_supply) {
printk("[---- SBA ----] %s: vbus supply not ready, defering probe\n", __func__);
return -EPROBE_DEFER;
}
printk("[---- SBA ----] %s: Got pointer to vbus-supply\n", __func__);
}
else {
printk("[---- SBA ----] %s: Required vbus-supply-name property not given !\n", __func__);
return -EINVAL;
}
printk("[---- SBA ----] %s: Got pointer to vbus-supply\n", __func__);
}
else {
printk("[---- SBA ----] %s: Required vbus-supply-name property not given !\n", __func__);
return -EINVAL;
}
if (of_find_property(np, "one-wire-tty-name", NULL)) {
printk("[---- SBA ----] %s: Found one-wire-tty-name property, trying to read it\n", __func__);
ret = of_property_read_string(np, "one-wire-tty-name", otgc_data->one_wire_tty_name);
if (ret) {
printk("[---- SBA ----] %s: Failed to read property one-wire-tty-name (code %d)\n", __func__, ret);
return ret;
}
}
else {
printk("%s: required property one-wire-tty-name not given !\n", __func__);
return -EINVAL;
}
if (of_find_property(np, "one-wire-tty-name", NULL)) {
printk("[---- SBA ----] %s: Found one-wire-tty-name property, trying to read it\n", __func__);
ret = of_property_read_string(np, "one-wire-tty-name", &otgc_data->one_wire_tty_name);
if (ret) {
printk("[---- SBA ----] %s: Failed to read property one-wire-tty-name (code %d)\n", __func__, ret);
return ret;
}
}
else {
printk("%s: required property one-wire-tty-name not given !\n", __func__);
return -EINVAL;
}
//if (of_find_property(np, "one-wire-gpios", NULL)) {
//printk("[---- SBA ----] %s: Found one-wire-gpio property, trying to read it\n", __func__);
// gpio_num = of_get_named_gpio(np, "one-wire-gpio", 0);
// if (gpio_num < 0) {
// printk("%s: Failed to read property one-wire-gpio (code %ld)\n", __func__, gpio_num);
// return gpio_num;
// }
// otgc_data->one_wire_gpio = gpio_to_desc(gpio_num);
if (of_find_property(np, "one-wire-gpios", NULL)) {
printk("[---- SBA ----] %s: Found one-wire-gpio property, trying to read it\n", __func__);
otgc_data->one_wire_gpio = devm_gpiod_get(otgc_data->dev, "one-wire", GPIOD_IN);
if (IS_ERR(otgc_data->one_wire_gpio)) {
printk("%s: Failed to read property one-wire-gpio (code %ld)\n", __func__, PTR_ERR(otgc_data->one_wire_gpio));
return PTR_ERR(otgc_data->one_wire_gpio);
}
}
else {
printk("%s: required property one-wire-gpio not given !\n", __func__);
return -EINVAL;
}
otgc_data->one_wire_gpio = devm_gpiod_get(otgc_data->dev, "one-wire", GPIOD_IN);
if (IS_ERR(otgc_data->one_wire_gpio)) {
printk("%s: Failed to read property one-wire-gpio (code %ld)\n", __func__, PTR_ERR(otgc_data->one_wire_gpio));
return PTR_ERR(otgc_data->one_wire_gpio);
}
//}
//else {
// printk("%s: required property one-wire-gpio not given !\n", __func__);
// return -EINVAL;
//}
return 0;
return 0;
}
#endif
static int rm_otgcontrol_probe(struct platform_device *pdev)
{
struct rm_otgcontrol_data *otgc_data;
struct rm_otgcontrol_platform_data *pdata;
struct rm_otgcontrol_data *otgc_data;
struct rm_otgcontrol_platform_data *pdata;
int ret = 0;
int ret = 0;
printk("[---- SBA ----] %s: Enter:\n", __func__);
printk("[---- SBA ----] %s: Enter:\n", __func__);
pr_info("%s: rM OTGCONTROL Driver Loading\n", __func__);
pr_info("%s: rM OTGCONTROL Driver Loading\n", __func__);
printk("[---- SBA ----] %s: Allocating otgcontrol_data\n", __func__);
otgc_data = devm_kzalloc(&pdev->dev, sizeof(struct rm_otgcontrol_data), GFP_KERNEL);
if (!otgc_data) {
printk("[---- SBA ----] %s: Failed to allocate otgc_data\n", __func__);
return -ENOMEM;
}
printk("[---- SBA ----] %s: Allocating otgcontrol_data\n", __func__);
otgc_data = devm_kzalloc(&pdev->dev, sizeof(struct rm_otgcontrol_data), GFP_KERNEL);
if (!otgc_data) {
printk("[---- SBA ----] %s: Failed to allocate otgc_data\n", __func__);
return -ENOMEM;
}
printk("[---- SBA ----] %s: Allocating otgcontrol_data\n", __func__);
pdata = devm_kzalloc(&pdev->dev, sizeof(struct rm_otgcontrol_platform_data), GFP_KERNEL);
if (unlikely(!pdata)) {
pr_err("[---- SBA ----] %s: Failed to allocate pdata\n", __func__);
pdata = ERR_PTR(-ENOMEM);
ret = -ENOMEM;
goto error_1;
}
printk("[---- SBA ----] %s: Allocating otgcontrol_data\n", __func__);
pdata = devm_kzalloc(&pdev->dev, sizeof(struct rm_otgcontrol_platform_data), GFP_KERNEL);
if (unlikely(!pdata)) {
pr_err("[---- SBA ----] %s: Failed to allocate pdata\n", __func__);
pdata = ERR_PTR(-ENOMEM);
ret = -ENOMEM;
goto error_1;
}
otgc_data->dev = &pdev->dev;
otgc_data->pdata = pdata;
otgc_data->dev = &pdev->dev;
otgc_data->pdata = pdata;
#if defined(CONFIG_OF)
printk("[---- SBA ---] %s: Reading platform data from devicetree\n", __func__);
ret = rm_otgcontrol_parse_dt(otgc_data);
if (ret < 0) {
pr_err("[---- SBA ----] %s: Failed to load platform data from devicetree\n", __func__);
goto error_2;
}
printk("[---- SBA ---] %s: Reading platform data from devicetree\n", __func__);
ret = rm_otgcontrol_parse_dt(otgc_data);
if (ret < 0) {
pr_err("[---- SBA ----] %s: Failed to load platform data from devicetree\n", __func__);
goto error_2;
}
#else
printk("[---- SBA ----] %s: Driver does not support non-dt configuration\n", __func__);
ret = -ENOTSUP;
goto error_2;
printk("[---- SBA ----] %s: Driver does not support non-dt configuration\n", __func__);
ret = -ENOTSUP;
goto error_2;
#endif
printk("[---- SBA ----] %s: Setting otgc_data reference in pdev, and initiating\n", __func__);
ret = rm_otgcontrol_init(otgc_data);
if(ret < 0)
goto error_3;
printk("[---- SBA ----] %s: Setting otgc_data reference in pdev, and initiating\n", __func__);
ret = rm_otgcontrol_init(otgc_data);
if(ret < 0)
goto error_3;
platform_set_drvdata(pdev, otgc_data);
return 0;
platform_set_drvdata(pdev, otgc_data);
return 0;
error_1:
kfree(otgc_data);
return ret;
kfree(otgc_data);
return ret;
error_2:
kfree(pdata);
kfree(otgc_data);
return ret;
kfree(pdata);
kfree(otgc_data);
return ret;
error_3:
otgcontrol_uninit_sysfs_nodes(otgc_data);
otgcontrol_uninit_extcon(otgc_data);
kfree(pdata);
kfree(otgc_data);
return ret;
otgcontrol_uninit_sysfs_nodes(otgc_data);
otgcontrol_uninit_extcon(otgc_data);
kfree(pdata);
kfree(otgc_data);
return ret;
}
static int rm_otgcontrol_remove(struct platform_device *pdev)
{
struct rm_otgcontrol_data *otgc_data = platform_get_drvdata(pdev);
struct rm_otgcontrol_data *otgc_data = platform_get_drvdata(pdev);
printk("[---- SBA ----]otgcontrol1 %s Enter:\n", __func__);
printk("[---- SBA ----]otgcontrol1 %s Enter:\n", __func__);
printk("%s: Un-initializing sysfs nodes\n", __func__);
otgcontrol_uninit_sysfs_nodes(otgc_data);
printk("%s: Un-initializing sysfs nodes\n", __func__);
otgcontrol_uninit_sysfs_nodes(otgc_data);
printk("%s: Un-initializing extcon device\n", __func__);
otgcontrol_uninit_extcon(otgc_data);
printk("%s: Un-initializing extcon device\n", __func__);
otgcontrol_uninit_extcon(otgc_data);
printk("%s: Freeing otgc->pdata\n", __func__);
kfree(otgc_data->pdata);
printk("%s: Freeing otgc->pdata\n", __func__);
kfree(otgc_data->pdata);
printk("%s: Freeing otgc\n", __func__);
kfree(otgc_data);
printk("%s: Freeing otgc\n", __func__);
kfree(otgc_data);
return 0;
return 0;
}
#if defined CONFIG_PM
static int rm_otgcontrol_suspend(struct device *dev)
{
printk("[---- SBA ----] %s Enter:\n", __func__);
printk("[---- SBA ----] %s Enter:\n", __func__);
return 0;
return 0;
}
static int rm_otgcontrol_resume(struct device *dev)
{
printk("[---- SBA ----] %s Enter:\n", __func__);
printk("[---- SBA ----] %s Enter:\n", __func__);
return 0;
return 0;
}
#else
#define rm_otgcontrol_suspend NULL
@ -257,47 +257,47 @@ static int rm_otgcontrol_resume(struct device *dev)
#ifdef CONFIG_OF
static struct of_device_id rm_otgcontrol_dt_ids[] = {
{ .compatible = "rm-otgcontrol" },
{ }
{ .compatible = "rm-otgcontrol" },
{ }
};
MODULE_DEVICE_TABLE(of, rm_otgcontrol_dt_ids);
#endif
static SIMPLE_DEV_PM_OPS(rm_otgcontrol_pm_ops,
rm_otgcontrol_suspend,
rm_otgcontrol_resume);
rm_otgcontrol_suspend,
rm_otgcontrol_resume);
static struct platform_driver rm_otgcontrol_driver = {
.driver = {
.name = "rM OTG Control",
.owner = THIS_MODULE,
.driver = {
.name = "rM OTG Control",
.owner = THIS_MODULE,
#ifdef CONFIG_PM
.pm = &rm_otgcontrol_pm_ops,
.pm = &rm_otgcontrol_pm_ops,
#endif
#ifdef CONFIG_OF
.of_match_table = rm_otgcontrol_dt_ids,
.of_match_table = rm_otgcontrol_dt_ids,
#endif
},
.probe = rm_otgcontrol_probe,
.remove = rm_otgcontrol_remove,
},
.probe = rm_otgcontrol_probe,
.remove = rm_otgcontrol_remove,
};
static int __init otgcontrol_init(void)
{
int ret;
int ret;
printk("%s: Registering platform driver 'rm-otgcontrol'\n", __func__);
ret = platform_driver_register(&rm_otgcontrol_driver);
if (ret < 0)
printk("%s: Failed to register platform driver 'rm-otgcontrol', code %d\n", __func__, ret);
printk("%s: Registering platform driver 'rm-otgcontrol'\n", __func__);
ret = platform_driver_register(&rm_otgcontrol_driver);
if (ret < 0)
printk("%s: Failed to register platform driver 'rm-otgcontrol', code %d\n", __func__, ret);
return ret;
return ret;
}
static void __exit otgcontrol_exit(void)
{
printk("%s: Unregistering platform driver 'rm-otgcontrol'\n", __func__);
platform_driver_unregister(&rm_otgcontrol_driver);
printk("%s: Unregistering platform driver 'rm-otgcontrol'\n", __func__);
platform_driver_unregister(&rm_otgcontrol_driver);
}
module_init(otgcontrol_init);

View File

@ -9,182 +9,294 @@
#include <linux/workqueue.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#define ONE_WIRE_GPIO_DEBOUNCE_MS 200 /* ms */
#define ONE_WIRE_GPIO_DEBOUNCE_MS 200 /* ms */
int otgcontrol_init_one_wire_mux_state(struct rm_otgcontrol_data *otgc_data)
{
int ret;
int ret;
printk("%s: Initiating one-wire pinctrl states\n", __func__);
otgc_data->one_wire_pinctrl = devm_pinctrl_get(otgc_data->dev);
if (IS_ERR(otgc_data->one_wire_pinctrl)) {
printk("%s: Failed to get pinctrl\n", __func__);
return PTR_ERR(otgc_data->one_wire_pinctrl);
}
printk("%s: Initiating one-wire pinctrl states\n", __func__);
otgc_data->one_wire_pinctrl = devm_pinctrl_get(otgc_data->dev);
if (IS_ERR(otgc_data->one_wire_pinctrl)) {
printk("%s: Failed to get pinctrl\n", __func__);
return PTR_ERR(otgc_data->one_wire_pinctrl);
}
otgc_data->one_wire_pinctrl_states[OTG1_ONEWIRE_STATE__GPIO] = pinctrl_lookup_state(otgc_data->one_wire_pinctrl, "default");
if (IS_ERR(otgc_data->one_wire_pinctrl_states[OTG1_ONEWIRE_STATE__GPIO])) {
printk("%s: Failed to configure one-wire-gpio state\n", __func__);
devm_pinctrl_put(otgc_data->one_wire_pinctrl);
return PTR_ERR(otgc_data->one_wire_pinctrl_states[OTG1_ONEWIRE_STATE__GPIO]);
}
otgc_data->one_wire_pinctrl_states[OTG1_ONEWIRE_STATE__GPIO] = pinctrl_lookup_state(otgc_data->one_wire_pinctrl, "default");
if (IS_ERR(otgc_data->one_wire_pinctrl_states[OTG1_ONEWIRE_STATE__GPIO])) {
printk("%s: Failed to configure one-wire-gpio state\n", __func__);
devm_pinctrl_put(otgc_data->one_wire_pinctrl);
return PTR_ERR(otgc_data->one_wire_pinctrl_states[OTG1_ONEWIRE_STATE__GPIO]);
}
otgc_data->one_wire_pinctrl_states[OTG1_ONEWIRE_STATE__UART_TX] = pinctrl_lookup_state(otgc_data->one_wire_pinctrl, "one_wire_uart_tx");
if (IS_ERR(otgc_data->one_wire_pinctrl_states[OTG1_ONEWIRE_STATE__UART_TX])) {
printk("%s: Failed to configure one-wire-uart-tx state\n", __func__);
devm_pinctrl_put(otgc_data->one_wire_pinctrl);
return PTR_ERR(otgc_data->one_wire_pinctrl_states[OTG1_ONEWIRE_STATE__UART_TX]);
}
otgc_data->one_wire_pinctrl_states[OTG1_ONEWIRE_STATE__UART_TX] = pinctrl_lookup_state(otgc_data->one_wire_pinctrl, "one_wire_uart_tx");
if (IS_ERR(otgc_data->one_wire_pinctrl_states[OTG1_ONEWIRE_STATE__UART_TX])) {
printk("%s: Failed to configure one-wire-uart-tx state\n", __func__);
devm_pinctrl_put(otgc_data->one_wire_pinctrl);
return PTR_ERR(otgc_data->one_wire_pinctrl_states[OTG1_ONEWIRE_STATE__UART_TX]);
}
otgc_data->one_wire_pinctrl_states[OTG1_ONEWIRE_STATE__UART_RX] = pinctrl_lookup_state(otgc_data->one_wire_pinctrl, "one_wire_uart_rx");
if (IS_ERR(otgc_data->one_wire_pinctrl_states[OTG1_ONEWIRE_STATE__UART_RX])) {
printk("%s: Failed to configure one-wire-uart-rx\n", __func__);
devm_pinctrl_put(otgc_data->one_wire_pinctrl);
return PTR_ERR(otgc_data->one_wire_pinctrl_states[OTG1_ONEWIRE_STATE__UART_RX]);
}
otgc_data->one_wire_pinctrl_states[OTG1_ONEWIRE_STATE__UART_RX] = pinctrl_lookup_state(otgc_data->one_wire_pinctrl, "one_wire_uart_rx");
if (IS_ERR(otgc_data->one_wire_pinctrl_states[OTG1_ONEWIRE_STATE__UART_RX])) {
printk("%s: Failed to configure one-wire-uart-rx\n", __func__);
devm_pinctrl_put(otgc_data->one_wire_pinctrl);
return PTR_ERR(otgc_data->one_wire_pinctrl_states[OTG1_ONEWIRE_STATE__UART_RX]);
}
printk("%s: Setting default state (GPIO)\n", __func__);
ret = pinctrl_select_state(otgc_data->one_wire_pinctrl, otgc_data->one_wire_pinctrl_states[OTG1_ONEWIRE_STATE__GPIO]);
if (ret < 0) {
printk("%s: Failed to set default state (GPIO)\n", __func__);
devm_pinctrl_put(otgc_data->one_wire_pinctrl);
return ret;
}
return 0;
printk("%s: Setting default state (GPIO)\n", __func__);
ret = pinctrl_select_state(otgc_data->one_wire_pinctrl, otgc_data->one_wire_pinctrl_states[OTG1_ONEWIRE_STATE__GPIO]);
if (ret < 0) {
printk("%s: Failed to set default state (GPIO)\n", __func__);
devm_pinctrl_put(otgc_data->one_wire_pinctrl);
return ret;
}
return 0;
}
void otgcontrol_uninit_onw_wire_mux_state(struct rm_otgcontrol_data *otgc_data)
{
devm_pinctrl_put(otgc_data->one_wire_pinctrl);
devm_pinctrl_put(otgc_data->one_wire_pinctrl);
}
int otgcontrol_switch_one_wire_mux_state(struct rm_otgcontrol_data *otgc_data, int state)
{
int ret;
printk("%s: Enter\n", __func__);
int ret;
switch(state)
{
case OTG1_ONEWIRE_STATE__GPIO:
printk("%s: Switching onewire state -> GPIO\n", __func__);
ret = pinctrl_select_state(otgc_data->one_wire_pinctrl, otgc_data->one_wire_pinctrl_states[OTG1_ONEWIRE_STATE__GPIO]);
if (ret < 0) {
printk("%s: Failed to set pinctrl state\n", __func__);
return ret;
}
break;
switch(state)
{
case OTG1_ONEWIRE_STATE__GPIO:
printk("%s: Switching onewire state -> GPIO\n", __func__);
ret = pinctrl_select_state(otgc_data->one_wire_pinctrl, otgc_data->one_wire_pinctrl_states[OTG1_ONEWIRE_STATE__GPIO]);
if (ret < 0) {
printk("%s: Failed to set pinctrl state\n", __func__);
return ret;
}
break;
case OTG1_ONEWIRE_STATE__UART_RX:
printk("%s: Switching onewire state -> UART RX\n", __func__);
ret = pinctrl_select_state(otgc_data->one_wire_pinctrl, otgc_data->one_wire_pinctrl_states[OTG1_ONEWIRE_STATE__UART_RX]);
if (ret < 0) {
printk("%s: Failed to set pinctrl state\n", __func__);
return ret;
}
break;
case OTG1_ONEWIRE_STATE__UART_RX:
printk("%s: Switching onewire state -> UART RX\n", __func__);
ret = pinctrl_select_state(otgc_data->one_wire_pinctrl, otgc_data->one_wire_pinctrl_states[OTG1_ONEWIRE_STATE__UART_RX]);
if (ret < 0) {
printk("%s: Failed to set pinctrl state\n", __func__);
return ret;
}
break;
case OTG1_ONEWIRE_STATE__UART_TX:
printk("%s: switching onewire state -> UART TX\n", __func__);
ret = pinctrl_select_state(otgc_data->one_wire_pinctrl, otgc_data->one_wire_pinctrl_states[OTG1_ONEWIRE_STATE__UART_TX]);
if (ret < 0) {
printk("%s: Failed to set pinctrl state\n", __func__);
return ret;
}
break;
case OTG1_ONEWIRE_STATE__UART_TX:
printk("%s: switching onewire state -> UART TX\n", __func__);
ret = pinctrl_select_state(otgc_data->one_wire_pinctrl, otgc_data->one_wire_pinctrl_states[OTG1_ONEWIRE_STATE__UART_TX]);
if (ret < 0) {
printk("%s: Failed to set pinctrl state\n", __func__);
return ret;
}
break;
default:
printk("%s: unable to switch onewire state (unknown state %d)\n", __func__, state);
return -EINVAL;
}
default:
printk("%s: unable to switch onewire state (unknown state %d)\n", __func__, state);
return -EINVAL;
}
return 0;
return 0;
}
int otgcontrol_get_current_gpio_state(struct rm_otgcontrol_data *otgc_data)
{
printk("%s: Enter\n", __func__);
return gpiod_get_raw_value(otgc_data->one_wire_gpio);
printk("%s: Enter\n", __func__);
return gpiod_get_raw_value(otgc_data->one_wire_gpio);
}
int otgcontrol_init_gpio_irq(struct rm_otgcontrol_data *otgc_data)
{
int ret;
int ret;
printk("%s: Enter\n", __func__);
printk("%s: Enter\n", __func__);
printk("%s: Setting local gpio debounce jiffies\n", __func__);
otgc_data->one_wire_gpio_debounce_jiffies = msecs_to_jiffies(ONE_WIRE_GPIO_DEBOUNCE_MS);
printk("%s: Setting local gpio debounce jiffies\n", __func__);
otgc_data->one_wire_gpio_debounce_jiffies = msecs_to_jiffies(ONE_WIRE_GPIO_DEBOUNCE_MS);
printk("%s: Initiating irq worker\n", __func__);
INIT_DELAYED_WORK(&otgc_data->one_wire_gpio_irq_work_queue, otgcontrol_gpio_irq_work);
printk("%s: Initiating irq worker\n", __func__);
INIT_DELAYED_WORK(&otgc_data->one_wire_gpio_irq_work_queue, otgcontrol_gpio_irq_work);
printk("%s: Getting IRQ from given gpio (%d)\n",
__func__,
desc_to_gpio(otgc_data->one_wire_gpio));
otgc_data->one_wire_gpio_irq = gpiod_to_irq(otgc_data->one_wire_gpio);
if (otgc_data->one_wire_gpio_irq < 0) {
dev_err(otgc_data->dev, "%s: Failed to get irq for given gpio (%d)\n",
__func__,
desc_to_gpio(otgc_data->one_wire_gpio));
return otgc_data->one_wire_gpio_irq;
}
printk("%s: Getting IRQ from given gpio (%d)\n",
__func__,
desc_to_gpio(otgc_data->one_wire_gpio));
otgc_data->one_wire_gpio_irq = gpiod_to_irq(otgc_data->one_wire_gpio);
if (otgc_data->one_wire_gpio_irq < 0) {
dev_err(otgc_data->dev, "%s: Failed to get irq for given gpio (%d)\n",
__func__,
desc_to_gpio(otgc_data->one_wire_gpio));
return otgc_data->one_wire_gpio_irq;
}
printk("%s: Requesting threaded irq\n", __func__);
ret = devm_request_threaded_irq(otgc_data->dev, otgc_data->one_wire_gpio_irq, NULL,
otgcontrol_gpio_irq_handler,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"one_wire_gpio_irq", otgc_data);
if (ret < 0) {
dev_err(otgc_data->dev, "%s: Failed to request handler for IRQ (%d) given for GPIO (%d)\n",
__func__,
otgc_data->one_wire_gpio_irq,
desc_to_gpio(otgc_data->one_wire_gpio));
return ret;
}
printk("%s: Requesting threaded irq\n", __func__);
ret = devm_request_threaded_irq(otgc_data->dev, otgc_data->one_wire_gpio_irq, NULL,
otgcontrol_gpio_irq_handler,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"one_wire_gpio_irq", otgc_data);
if (ret < 0) {
dev_err(otgc_data->dev, "%s: Failed to request handler for IRQ (%d) given for GPIO (%d)\n",
__func__,
otgc_data->one_wire_gpio_irq,
desc_to_gpio(otgc_data->one_wire_gpio));
return ret;
}
otgc_data->one_wire_gpio_irq_is_active = true;
return 0;
return 0;
}
void otgcontrol_activate_gpio_irq(struct rm_otgcontrol_data *otgc_data)
{
printk("%s: Enter\n", __func__);
enable_irq(otgc_data->one_wire_gpio_irq);
if (!otgc_data->one_wire_gpio_irq_is_active) {
enable_irq(otgc_data->one_wire_gpio_irq);
otgc_data->one_wire_gpio_irq_is_active = true;
}
}
void otgcontrol_deactivate_gpio_irq(struct rm_otgcontrol_data *otgc_data)
{
printk("%s: Enter\n", __func__);
disable_irq(otgc_data->one_wire_gpio_irq);
if (otgc_data->one_wire_gpio_irq_is_active) {
disable_irq(otgc_data->one_wire_gpio_irq);
otgc_data->one_wire_gpio_irq_is_active = false;
}
}
static irqreturn_t otgcontrol_gpio_irq_handler(int irq, void *data)
{
struct rm_otgcontrol_data *otgc_data = (struct rm_otgcontrol_data*)data;
struct rm_otgcontrol_data *otgc_data = (struct rm_otgcontrol_data*)data;
printk("%s: Enter\n", __func__);
/* otgcontrol_deactivate_gpio_irq(otgc_data); */
queue_delayed_work(system_power_efficient_wq, &otgc_data->one_wire_gpio_irq_work_queue, otgc_data->one_wire_gpio_debounce_jiffies);
printk("%s: Enter\n", __func__);
/* otgcontrol_deactivate_gpio_irq(otgc_data); */
queue_delayed_work(system_power_efficient_wq, &otgc_data->one_wire_gpio_irq_work_queue, otgc_data->one_wire_gpio_debounce_jiffies);
return IRQ_HANDLED;
return IRQ_HANDLED;
}
static void otgcontrol_gpio_irq_work(struct work_struct *work)
{
int cur_gpio_state;
int cur_gpio_state;
struct delayed_work *delayed_work = container_of(work, struct delayed_work, work);
struct rm_otgcontrol_data *otgc_data = container_of(delayed_work, struct rm_otgcontrol_data, one_wire_gpio_irq_work_queue);
struct delayed_work *delayed_work = container_of(work, struct delayed_work, work);
struct rm_otgcontrol_data *otgc_data = container_of(delayed_work, struct rm_otgcontrol_data, one_wire_gpio_irq_work_queue);
printk("%s: Enter\n", __func__);
printk("%s: Enter\n", __func__);
cur_gpio_state = otgcontrol_get_current_gpio_state(otgc_data);
if (cur_gpio_state != otgc_data->one_wire_state) {
printk("%s: GPIO state changed -> %s\n", __func__, cur_gpio_state ? "HIGH" : "LOW");
otgc_data->one_wire_state = cur_gpio_state;
cur_gpio_state = otgcontrol_get_current_gpio_state(otgc_data);
if (cur_gpio_state != otgc_data->one_wire_state) {
printk("%s: GPIO state changed -> %s\n", __func__, cur_gpio_state ? "HIGH" : "LOW");
otgc_data->one_wire_state = cur_gpio_state;
otgcontrol_handleInput(otgc_data, OTG1_EVENT__ONEWIRE_GPIO_STATE_CHANGED, (void*)&otgc_data->one_wire_state);
}
if (otgc_data->one_wire_state == 0)
otgcontrol_handleInput(otgc_data, OTG1_EVENT__DEVICE_CONNECTED, NULL);
else
otgcontrol_handleInput(otgc_data, OTG1_EVENT__DEVICE_DISCONNECTED, NULL);
}
/* otgcontrol_activate_gpio_irq(otgc_data); */
/* otgcontrol_activate_gpio_irq(otgc_data); */
}
int otgcontrol_onewire_write_tty(char *device_name, char *text_to_send)
{
// Create variables
struct file *f;
char buf[128];
mm_segment_t fs;
int i;
// Init the buffer with 0
for(i = 0;i < 128;i++)
buf[i] = 0;
printk("%s: Trying to open %s\n", __func__, device_name);
f = filp_open(device_name, O_RDWR, 0);
if(f == NULL) {
printk("%s: filp_open error!!.\n", __func__);
return -1;
}
else {
// Get current segment descriptor
printk("%s: Getting current segment descriptor\n", __func__);
fs = get_fs();
// Set segment descriptor associated to kernel space
printk("%s: Setting segment descriptor\n", __func__);
set_fs(get_ds());
//Write to the file
printk("%s: Writing '%s' to file\n", __func__, text_to_send);
kernel_write(f, text_to_send, strlen(text_to_send), &f->f_pos);
// f->f_op->write(f, text_to_send, strlen(text_to_send), &f->f_pos);
// Restore segment descriptor
printk("%s: Restoring segment descriptor\n", __func__);
set_fs(fs);
printk("%s: Closing file\n", __func__);
filp_close(f,NULL);
return 0;
}
}
int otgcontrol_onewire_read_until_cr(char *device_name, char *buf, int maxlen)
{
// Create variables
struct file *f;
mm_segment_t fs;
char newchar;
int pos;
f = filp_open(device_name, O_RDONLY, 0);
if(f == NULL) {
printk("%s: filp_open error!!.\n", __func__);
return -1;
}
else {
// Get current segment descriptor
printk("%s: Getting current segment descriptor\n", __func__);
fs = get_fs();
// Set segment descriptor associated to kernel space
printk("%s: Setting segment descriptor\n", __func__);
set_fs(get_ds());
pos = 0;
int state = 0;
printk("%s: Starting read loop\n", __func__);
do {
// Read the file
// f->f_op->read(f, &newchar, 1, &f->f_pos);
kernel_read(f, &newchar, 1, &f->f_pos);
printk("%s: <-%c (0x%02x)\n", __func__, newchar, newchar);
switch(state)
{
case 0:
// Wait :
if (newchar == ':') {
printk("%s: SOF\n", __func__);
state = 1;
}
break;
default:
// Reading chars
if (newchar != '#') {
buf[pos++] = newchar;
}
}
}while((newchar != '#') && (pos < maxlen));
printk("%s: Done\n", __func__);
// Restore segment descriptor
printk("%s: Restoring segment descriptor\n", __func__);
set_fs(fs);
printk("%s: Closing file\n", __func__);
filp_close(f,NULL);
printk("%s: Returning %d bytes read\n", __func__, pos);
return pos;
}
}

View File

@ -6,9 +6,9 @@
#include <linux/workqueue.h>
#include <linux/interrupt.h>
#define OTG1_ONEWIRE_STATE__GPIO 0
#define OTG1_ONEWIRE_STATE__UART_TX 1
#define OTG1_ONEWIRE_STATE__UART_RX 2
#define OTG1_ONEWIRE_STATE__GPIO 0
#define OTG1_ONEWIRE_STATE__UART_TX 1
#define OTG1_ONEWIRE_STATE__UART_RX 2
int otgcontrol_init_one_wire_mux_state(struct rm_otgcontrol_data *otgc_data);
void otgcontrol_uninit_onw_wire_mux_state(struct rm_otgcontrol_data *otgc_data);
@ -20,5 +20,7 @@ void otgcontrol_activate_gpio_irq(struct rm_otgcontrol_data *otgc_data);
void otgcontrol_deactivate_gpio_irq(struct rm_otgcontrol_data *otgc_data);
static irqreturn_t otgcontrol_gpio_irq_handler(int irq, void *data);
static void otgcontrol_gpio_irq_work(struct work_struct *work);
int otgcontrol_onewire_read_until_cr(char *device_name, char *buf, int maxlen);
int otgcontrol_onewire_write_tty(char *device_name, char *text_to_send);
#endif /* __OTGCONTROL_ONE_WIRE_H__ */

View File

@ -17,178 +17,176 @@
#define SYSFS_NODE_NAME "otgcontrol"
static ssize_t attribute_show(struct kobject *kobj, struct kobj_attribute *attr,
char *buf)
char *buf)
{
int var;
struct rm_otgcontrol_data *otgc_data;
int var;
struct rm_otgcontrol_data *otgc_data;
printk("%s: Enter\n", __func__);
printk("%s: Enter\n", __func__);
if (strcmp(attr->attr.name, "otg1_device_connected") == 0) {
otgc_data = to_otgcontrol_data(attr, otg1_device_connected_attribute);
printk("%s: Returning cur otg1_device_connected value (%d)\n", __func__, otgc_data->otg1_device_connected);
var = otgc_data->otg1_device_connected;
}
else if (strcmp(attr->attr.name, "otg1_dr_mode") == 0) {
otgc_data = to_otgcontrol_data(attr, otg1_dr_mode_attribute);
printk("%s: Returning cur otg1_id_state value (%d)\n", __func__, otgc_data->otg1_dr_mode);
var = otgc_data->otg1_dr_mode;
}
else if (strcmp(attr->attr.name, "otg1_chargermode") == 0) {
otgc_data = to_otgcontrol_data(attr, otg1_chargermode_attribute);
printk("%s: Returning cur otg1_chargermode value (%d)\n", __func__, otgc_data->otg1_chargermode);
var = otgc_data->otg1_chargermode;
}
else if (strcmp(attr->attr.name, "otg1_controllermode") == 0) {
otgc_data = to_otgcontrol_data(attr, otg1_controllermode_attribute);
printk("%s: Returning cur otg1_controllermode value (%d)\n", __func__, otgc_data->otg1_controllermode);
var = otgc_data->otg1_controllermode;
}
else {
printk("%s: Invalid attribute name (%s)\n", __func__, attr->attr.name);
return -EINVAL;
}
if (strcmp(attr->attr.name, "otg1_device_connected") == 0) {
otgc_data = to_otgcontrol_data(attr, otg1_device_connected_attribute);
printk("%s: Returning cur otg1_device_connected value (%d)\n", __func__, otgc_data->otg1_device_connected);
var = otgc_data->otg1_device_connected;
}
else if (strcmp(attr->attr.name, "otg1_dr_mode") == 0) {
otgc_data = to_otgcontrol_data(attr, otg1_dr_mode_attribute);
printk("%s: Returning cur otg1_id_state value (%d)\n", __func__, otgc_data->otg1_dr_mode);
var = otgc_data->otg1_dr_mode;
}
else if (strcmp(attr->attr.name, "otg1_chargermode") == 0) {
otgc_data = to_otgcontrol_data(attr, otg1_chargermode_attribute);
printk("%s: Returning cur otg1_chargermode value (%d)\n", __func__, otgc_data->otg1_chargermode);
var = otgc_data->otg1_chargermode;
}
else if (strcmp(attr->attr.name, "otg1_controllermode") == 0) {
otgc_data = to_otgcontrol_data(attr, otg1_controllermode_attribute);
printk("%s: Returning cur otg1_controllermode value (%d)\n", __func__, otgc_data->otg1_controllermode);
var = otgc_data->otg1_controllermode;
}
else {
printk("%s: Invalid attribute name (%s)\n", __func__, attr->attr.name);
return -EINVAL;
}
return sprintf(buf, "%d\n", var);
return sprintf(buf, "%d\n", var);
}
static ssize_t attribute_store(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t count)
const char *buf, size_t count)
{
struct rm_otgcontrol_data *otgc_data;
int var, ret;
struct rm_otgcontrol_data *otgc_data;
int var, ret;
printk("%s: Enter\n", __func__);
printk("%s: Enter\n", __func__);
ret = kstrtoint(buf, 10, &var);
if (ret < 0)
return ret;
ret = kstrtoint(buf, 10, &var);
if (ret < 0)
return ret;
if (strcmp(attr->attr.name, "otg1_dr_mode") == 0) {
otgc_data = to_otgcontrol_data(attr, otg1_dr_mode_attribute);
printk("%s: Setting new otg1 dr mode (%d)\n", __func__, var);
ret = otgcontrol_set_dr_mode(otgc_data, var);
}
else if (strcmp(attr->attr.name, "otg1_chargermode") == 0) {
otgc_data = to_otgcontrol_data(attr, otg1_chargermode_attribute);
printk("%s: Setting new otg1 chargermode (%d)\n", __func__, var);
ret = otgcontrol_change_otg_charge_mode(otgc_data, var);
}
else if (strcmp(attr->attr.name, "otg1_controllermode") == 0) {
otgc_data = to_otgcontrol_data(attr, otg1_controllermode_attribute);
printk("%s: Setting new otg1 controllermode (%d)\n", __func__, var);
ret = otgcontrol_handleInput(otgc_data, OTG1_EVENT__MODE_CHANGE_REQUESTED, (void*)&var);
}
else if (strcmp(attr->attr.name, "otg1_pinctrlstate") == 0) {
otgc_data = to_otgcontrol_data(attr, otg1_pinctrlstate_attribute);
printk("%s: Setting new pinctrlstate (%d)\n", __func__, var);
ret = otgcontrol_switch_one_wire_mux_state(otgc_data, var);
}
else {
return -EINVAL;
}
if (strcmp(attr->attr.name, "otg1_dr_mode") == 0) {
otgc_data = to_otgcontrol_data(attr, otg1_dr_mode_attribute);
printk("%s: Setting new otg1 dr mode (%d)\n", __func__, var);
ret = otgcontrol_set_dr_mode(otgc_data, var);
}
else if (strcmp(attr->attr.name, "otg1_chargermode") == 0) {
otgc_data = to_otgcontrol_data(attr, otg1_chargermode_attribute);
printk("%s: Setting new otg1 chargermode (%d)\n", __func__, var);
ret = otgcontrol_change_otg_charge_mode(otgc_data, var);
}
else if (strcmp(attr->attr.name, "otg1_controllermode") == 0) {
otgc_data = to_otgcontrol_data(attr, otg1_controllermode_attribute);
printk("%s: Setting new otg1 controllermode (%d)\n", __func__, var);
ret = otgcontrol_handleInput(otgc_data, OTG1_EVENT__MODE_CHANGE_REQUESTED, (void*)&var);
}
else if (strcmp(attr->attr.name, "otg1_pinctrlstate") == 0) {
otgc_data = to_otgcontrol_data(attr, otg1_pinctrlstate_attribute);
printk("%s: Setting new pinctrlstate (%d)\n", __func__, var);
ret = otgcontrol_switch_one_wire_mux_state(otgc_data, var);
}
else {
return -EINVAL;
}
return count;
return count;
}
void otgcontrol_create_kobj_property(struct kobj_attribute *attr,
const char *name,
int permission,
ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr, char *buf),
ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count))
const char *name,
int permission,
ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr, char *buf),
ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count))
{
attr->attr.name = name;
attr->attr.mode = VERIFY_OCTAL_PERMISSIONS(S_IRUGO | S_IWUSR);
attr->show = show;
attr->store = store;
attr->attr.name = name;
attr->attr.mode = VERIFY_OCTAL_PERMISSIONS(S_IRUGO | S_IWUSR);
attr->show = show;
attr->store = store;
}
int otgcontrol_init_sysfs_nodes(struct rm_otgcontrol_data *otgc_data)
{
struct kobject *otgcontrol_kobj;
int retval;
struct kobject *otgcontrol_kobj;
int retval;
printk("%s: Enter\n", __func__);
printk("%s: Enter\n", __func__);
printk("%s: Creating control properties (R/W)\n", __func__);
otgcontrol_create_kobj_property(&otgc_data->otg1_dr_mode_attribute,
"otg1_dr_mode",
S_IRUGO | S_IWUSR,
attribute_show,
attribute_store);
printk("%s: Creating control properties (R/W)\n", __func__);
otgcontrol_create_kobj_property(&otgc_data->otg1_dr_mode_attribute,
"otg1_dr_mode",
S_IRUGO | S_IWUSR,
attribute_show,
attribute_store);
otgcontrol_create_kobj_property(&otgc_data->otg1_chargermode_attribute,
"otg1_chargermode",
S_IRUGO | S_IWUSR,
attribute_show,
attribute_store);
otgcontrol_create_kobj_property(&otgc_data->otg1_chargermode_attribute,
"otg1_chargermode",
S_IRUGO | S_IWUSR,
attribute_show,
attribute_store);
otgcontrol_create_kobj_property(&otgc_data->otg1_controllermode_attribute,
"otg1_controllermode",
S_IRUGO | S_IWUSR,
attribute_show,
attribute_store);
otgcontrol_create_kobj_property(&otgc_data->otg1_controllermode_attribute,
"otg1_controllermode",
S_IRUGO | S_IWUSR,
attribute_show,
attribute_store);
otgcontrol_create_kobj_property(&otgc_data->otg1_pinctrlstate_attribute,
"otg1_pinctrlstate",
S_IRUGO | S_IWUSR,
attribute_show,
attribute_store);
otgcontrol_create_kobj_property(&otgc_data->otg1_pinctrlstate_attribute,
"otg1_pinctrlstate",
S_IRUGO | S_IWUSR,
attribute_show,
attribute_store);
struct attribute *control_attrs[] = {
&otgc_data->otg1_dr_mode_attribute.attr,
&otgc_data->otg1_chargermode_attribute.attr,
&otgc_data->otg1_controllermode_attribute.attr,
&otgc_data->otg1_pinctrlstate_attribute.attr,
NULL, /* need to NULL terminate the list of attributes */
};
struct attribute *control_attrs[] = {
&otgc_data->otg1_dr_mode_attribute.attr,
&otgc_data->otg1_chargermode_attribute.attr,
&otgc_data->otg1_controllermode_attribute.attr,
&otgc_data->otg1_pinctrlstate_attribute.attr,
NULL, /* need to NULL terminate the list of attributes */
};
printk("%s: Creating status properties (R)\n", __func__);
otgcontrol_create_kobj_property(&otgc_data->otg1_device_connected_attribute,
"otg1_device_connected",
S_IRUGO,
attribute_show,
attribute_store);
printk("%s: Creating status properties (R)\n", __func__);
otgcontrol_create_kobj_property(&otgc_data->otg1_device_connected_attribute,
"otg1_device_connected",
S_IRUGO,
attribute_show,
attribute_store);
struct attribute *status_attrs[] = {
&otgc_data->otg1_device_connected_attribute.attr,
NULL, /* need to NULL terminate the list of attributes */
};
struct attribute *status_attrs[] = {
&otgc_data->otg1_device_connected_attribute.attr,
NULL, /* need to NULL terminate the list of attributes */
};
struct attribute_group control_attr_group = {
.attrs = control_attrs,
.name = "control"
};
struct attribute_group control_attr_group = {
.attrs = control_attrs,
.name = "control"
};
struct attribute_group status_attr_group = {
.attrs = status_attrs,
.name = "status"
};
struct attribute_group status_attr_group = {
.attrs = status_attrs,
.name = "status"
};
otgcontrol_kobj = kobject_create_and_add(SYSFS_NODE_NAME, SYSFS_PARENT_NODE);
if (!otgcontrol_kobj)
return -ENOMEM;
otgcontrol_kobj = kobject_create_and_add(SYSFS_NODE_NAME, SYSFS_PARENT_NODE);
if (!otgcontrol_kobj)
return -ENOMEM;
/* Create the files associated with this kobject */
retval = sysfs_create_group(otgcontrol_kobj, &control_attr_group);
retval = sysfs_create_group(otgcontrol_kobj, &status_attr_group);
if (retval) {
otgc_data->kobject = otgcontrol_kobj;
}
/* Create the files associated with this kobject */
retval = sysfs_create_group(otgcontrol_kobj, &control_attr_group);
retval = sysfs_create_group(otgcontrol_kobj, &status_attr_group);
if (retval) {
otgc_data->kobject = otgcontrol_kobj;
}
kobject_put(otgc_data->kobject);
return retval;
kobject_put(otgc_data->kobject);
return retval;
}
//EXPORT_SYMBOL(otgcontrol_init_sysfs_nodes);
void otgcontrol_uninit_sysfs_nodes(struct rm_otgcontrol_data *otgc_data)
{
printk("%s: Enter\n", __func__);
printk("%s: Decrementing kobject refcount\n", __func__);
if((otgc_data->kobject != NULL) && !IS_ERR(otgc_data->kobject)) {
kobject_put(otgc_data->kobject);
otgc_data->kobject = NULL;
}
printk("%s: Enter\n", __func__);
printk("%s: Decrementing kobject refcount\n", __func__);
if((otgc_data->kobject != NULL) && !IS_ERR(otgc_data->kobject)) {
kobject_put(otgc_data->kobject);
otgc_data->kobject = NULL;
}
}
//EXPORT_SYMBOL(otgcontrol_uninit_sysfs_nodes);

View File

@ -1,4 +1,4 @@
'#ifndef __RM_OTGCONTROL_H_
#ifndef __RM_OTGCONTROL_H_
#define __RM_OTGCONTROL_H_
#include <linux/kobject.h>
@ -6,44 +6,44 @@
#include <linux/extcon.h>
struct rm_otgcontrol_platform_data {
struct power_supply *vbus_supply;
struct power_supply *vbus_supply;
};
struct rm_otgcontrol_data {
struct device *dev;
struct rm_otgcontrol_platform_data *pdata;
struct device *dev;
struct rm_otgcontrol_platform_data *pdata;
struct extcon_dev *extcon_dev;
struct extcon_dev *extcon_dev;
int otg_controlstate;
const char *one_wire_tty_name;
struct gpio_desc *one_wire_gpio;
int one_wire_gpio_irq;
unsigned long one_wire_gpio_debounce_jiffies;
struct delayed_work one_wire_gpio_irq_work_queue;
bool one_wire_gpio_irq_is_active;
const char *one_wire_tty_name[10]; /* Name of the tty device connected to the one-wire interface pin */
struct gpio_desc *one_wire_gpio; /* GPIO descriptor for GPIO connected to the one-wire-interface pin */
int one_wire_gpio_irq; /* IRQ num for the GPIO num connected to the one-wire-interface pin */
unsigned long one_wire_gpio_debounce_jiffies; /* Amount of jiffies corresponding to the defined debounce interval for the GPIO irq */
struct delayed_work one_wire_gpio_irq_work_queue; /* Work queue used to do IRQ handling async/somewhat delayed/debounced */
int otg_controlstate;
int mode_requested;
int otg_controlstate;
int one_wire_state;
struct pinctrl* one_wire_pinctrl;
struct pinctrl_state* one_wire_pinctrl_states[3];
int one_wire_state; /* The last read state of the one-wire GPIO input */
struct pinctrl* one_wire_pinctrl; /* Pinctrl object controlling the pin mux config for the one-wire pin */
struct pinctrl_state* one_wire_pinctrl_states[3]; /* The three pin mux definitions (pinmux states) to choose from */
struct kobject* kobject;
struct kobj_attribute otg1_device_connected_attribute;
bool otg1_device_connected;
struct kobject* kobject;
struct kobj_attribute otg1_device_connected_attribute;
bool otg1_device_connected;
struct kobj_attribute otg1_dr_mode_attribute;
int otg1_dr_mode;
struct kobj_attribute otg1_dr_mode_attribute;
int otg1_dr_mode;
struct kobj_attribute otg1_chargermode_attribute;
int otg1_chargermode;
struct kobj_attribute otg1_chargermode_attribute;
int otg1_chargermode;
struct kobj_attribute otg1_controllermode_attribute;
int otg1_controllermode;
struct kobj_attribute otg1_controllermode_attribute;
int otg1_controllermode;
struct kobj_attribute otg1_pinctrlstate_attribute; /* Read/write property, read current overall control mode or change mode (MANULAL_CONTROL, ONEWIRE_AUTH, USB_NO_AUTH) */
int otg1_pinctrlstate;
struct kobj_attribute otg1_pinctrlstate_attribute;
int otg1_pinctrlstate;
};
#endif /* __RM_OTGCONTROL_H */