ioc: Add reset GPIO

This commit is contained in:
Markus Koch 2019-11-16 13:22:22 +01:00
parent b23252df95
commit 101117d0bc
2 changed files with 81 additions and 16 deletions

View File

@ -1,18 +1,41 @@
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
index 5aff8ecc66cb..c8201e79dff3 100644 index c8201e79dff3..5407742acad6 100644
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts --- a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts +++ b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
@@ -211,9 +211,12 @@ @@ -210,12 +210,22 @@ &uart0 {
status = "okay";
}; };
+&pio {
+ lw35ioc_pins: lw35ioc-pins {
+ pins = "PA10";
+ function = "gpio_out";
+ };
+};
+
&uart1 { &uart1 {
+ status = "okay"; status = "okay";
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&uart1_pins>; pinctrl-0 = <&uart1_pins>;
- status = "disabled"; lw35ioc@0 {
+ lw35ioc@0 { compatible = "brother,lw35";
+ compatible = "brother,lw35"; + pinctrl-names = "default";
+ }; + pinctrl-0 = <&lw35ioc_pins>;
+ rst-gpios = <&pio 0 10 GPIO_ACTIVE_LOW>;
};
}; };
&uart2 { @@ -242,3 +252,13 @@ &usbphy {
/* VBUS on USB host ports are always on */
status = "okay";
};
+
+&spi0 {
+ status = "okay";
+ lmg6202ulyt@0 {
+ compatible = "hitachi,lmg6202ulyt";
+ reg = <0x0>;
+ spi-max-frequency = <2000000>;
+ cs-gpios = <0>, <&pio 0 3 GPIO_ACTIVE_LOW>;
+ };
+};

View File

@ -7,6 +7,7 @@
#include <linux/serdev.h> #include <linux/serdev.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/gpio/consumer.h>
// #define ENABLE_DEBUG ENABLE_DEBUG // #define ENABLE_DEBUG ENABLE_DEBUG
@ -43,20 +44,25 @@ static int keycode_map[] = {
KEY_SYSRQ KEY_SYSRQ
}; };
enum lw35ioc_state {SYNC, TYPE, KEYBOARD, PRINTER}; enum lw35ioc_state {PASSIVE, PASSTHROUGH, ACTIVE};
enum lw35ioc_packet_state {SYNC, TYPE, KEYBOARD, PRINTER};
struct lw35ioc_packet { struct lw35ioc_packet {
enum lw35ioc_state state; enum lw35ioc_packet_state state;
}; };
struct lw35ioc_priv { struct lw35ioc_priv {
struct serdev_device *serdev; struct serdev_device *serdev;
struct input_dev *input_dev; struct input_dev *input_dev;
struct gpio_desc *gpio_rst; /* GPIO to reset both AVRs */
enum lw35ioc_state state;
struct lw35ioc_packet packet; struct lw35ioc_packet packet;
}; };
static int lw35ioc_receive_buf(struct serdev_device *serdev,
static int lw35ioc_process_buf(struct serdev_device *serdev,
const unsigned char *data, const unsigned char *data,
size_t count) size_t count)
{ {
@ -107,6 +113,17 @@ static int lw35ioc_receive_buf(struct serdev_device *serdev,
return i; return i;
} }
static int lw35ioc_receive_buf(struct serdev_device *serdev,
const unsigned char *data,
size_t count)
{
struct lw35ioc_priv *priv = serdev_device_get_drvdata(serdev);
if (priv->state == ACTIVE)
return lw35ioc_process_buf(serdev, data, count);
return count; /* Pretend we read all data */
}
static void lw35ioc_write_wakeup(struct serdev_device *serdev) static void lw35ioc_write_wakeup(struct serdev_device *serdev)
{ {
dev_info(&serdev->dev, "Write wakeup\n"); dev_info(&serdev->dev, "Write wakeup\n");
@ -118,6 +135,14 @@ static struct serdev_device_ops lw35ioc_serdev_ops = {
.write_wakeup = lw35ioc_write_wakeup, .write_wakeup = lw35ioc_write_wakeup,
}; };
static void lw35ioc_set_hw_reset(struct serdev_device *serdev,
int reset_active)
{
struct lw35ioc_priv *priv = serdev_device_get_drvdata(serdev);
gpiod_set_value(priv->gpio_rst, !reset_active);
}
static int lw35ioc_probe(struct serdev_device *serdev) static int lw35ioc_probe(struct serdev_device *serdev)
{ {
struct lw35ioc_priv *priv = NULL; struct lw35ioc_priv *priv = NULL;
@ -128,6 +153,7 @@ static int lw35ioc_probe(struct serdev_device *serdev)
printk(KERN_INFO "lw35ioc: probe\n"); printk(KERN_INFO "lw35ioc: probe\n");
/* Allocate memory */
priv = devm_kzalloc(&serdev->dev, priv = devm_kzalloc(&serdev->dev,
sizeof(struct lw35ioc_priv), sizeof(struct lw35ioc_priv),
GFP_KERNEL); GFP_KERNEL);
@ -135,11 +161,13 @@ static int lw35ioc_probe(struct serdev_device *serdev)
printk(KERN_ERR "lw35ioc: Not enough memory.\n"); printk(KERN_ERR "lw35ioc: Not enough memory.\n");
return -ENOMEM; return -ENOMEM;
} }
priv->state = PASSIVE;
priv->serdev = serdev; priv->serdev = serdev;
priv->packet.state = SYNC; priv->packet.state = SYNC;
serdev_device_set_drvdata(serdev, priv); serdev_device_set_drvdata(serdev, priv);
serdev_device_set_client_ops(serdev, &lw35ioc_serdev_ops); serdev_device_set_client_ops(serdev, &lw35ioc_serdev_ops);
/* Register input device */
input_dev = devm_input_allocate_device(&serdev->dev); input_dev = devm_input_allocate_device(&serdev->dev);
if (!input_dev) { if (!input_dev) {
dev_err(&serdev->dev, "Unable to allocate input device.\n"); dev_err(&serdev->dev, "Unable to allocate input device.\n");
@ -156,25 +184,37 @@ static int lw35ioc_probe(struct serdev_device *serdev)
ret = input_register_device(input_dev); ret = input_register_device(input_dev);
if (ret) { if (ret) {
dev_err(&serdev->dev, "Unable to register input device.\n"); dev_err(&serdev->dev, "Unable to register input device.\n");
goto fail0; goto fail_input;
} }
ret = serdev_device_open(serdev); ret = serdev_device_open(serdev);
if (ret) { if (ret) {
dev_err(&serdev->dev, "Unable to open device.\n"); dev_err(&serdev->dev, "Unable to open device.\n");
goto fail1; goto fail_serdev;
} }
speed = serdev_device_set_baudrate(serdev, speed); speed = serdev_device_set_baudrate(serdev, speed);
dev_info(&serdev->dev, "Using baudrate: %u\n", speed); dev_info(&serdev->dev, "Using baudrate: %u\n", speed);
/* Register GPIO */
priv->gpio_rst = gpiod_get_index(&serdev->dev,
"rst",
0,
GPIOD_OUT_LOW);
lw35ioc_set_hw_reset(serdev, 0);
if (IS_ERR(priv->gpio_rst)) {
dev_err(&serdev->dev, "Unable to get reset GPIO.\n");
ret = -ENODEV;
goto fail_gpio;
}
dev_info(&serdev->dev, "Loaded driver.\n"); dev_info(&serdev->dev, "Loaded driver.\n");
return 0; return 0;
fail_gpio:
fail1: fail_serdev:
input_unregister_device(input_dev); input_unregister_device(input_dev);
fail0: fail_input:
devm_kfree(&serdev->dev, input_dev); devm_kfree(&serdev->dev, input_dev);
return ret; return ret;
} }
@ -183,6 +223,8 @@ static void lw35ioc_remove(struct serdev_device *serdev)
{ {
struct lw35ioc_priv *priv = serdev_device_get_drvdata(serdev); struct lw35ioc_priv *priv = serdev_device_get_drvdata(serdev);
lw35ioc_set_hw_reset(serdev, 1);
gpiod_put(priv->gpio_rst);
serdev_device_close(priv->serdev); serdev_device_close(priv->serdev);
input_unregister_device(priv->input_dev); input_unregister_device(priv->input_dev);