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
index 5aff8ecc66cb..c8201e79dff3 100644
index c8201e79dff3..5407742acad6 100644
--- a/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 {
+ status = "okay";
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&uart1_pins>;
- status = "disabled";
+ lw35ioc@0 {
+ compatible = "brother,lw35";
+ };
lw35ioc@0 {
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/types.h>
#include <linux/input.h>
#include <linux/gpio/consumer.h>
// #define ENABLE_DEBUG ENABLE_DEBUG
@ -43,20 +44,25 @@ static int keycode_map[] = {
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 {
enum lw35ioc_state state;
enum lw35ioc_packet_state state;
};
struct lw35ioc_priv {
struct serdev_device *serdev;
struct input_dev *input_dev;
struct gpio_desc *gpio_rst; /* GPIO to reset both AVRs */
enum lw35ioc_state state;
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,
size_t count)
{
@ -107,6 +113,17 @@ static int lw35ioc_receive_buf(struct serdev_device *serdev,
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)
{
dev_info(&serdev->dev, "Write wakeup\n");
@ -118,6 +135,14 @@ static struct serdev_device_ops lw35ioc_serdev_ops = {
.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)
{
struct lw35ioc_priv *priv = NULL;
@ -128,6 +153,7 @@ static int lw35ioc_probe(struct serdev_device *serdev)
printk(KERN_INFO "lw35ioc: probe\n");
/* Allocate memory */
priv = devm_kzalloc(&serdev->dev,
sizeof(struct lw35ioc_priv),
GFP_KERNEL);
@ -135,11 +161,13 @@ static int lw35ioc_probe(struct serdev_device *serdev)
printk(KERN_ERR "lw35ioc: Not enough memory.\n");
return -ENOMEM;
}
priv->state = PASSIVE;
priv->serdev = serdev;
priv->packet.state = SYNC;
serdev_device_set_drvdata(serdev, priv);
serdev_device_set_client_ops(serdev, &lw35ioc_serdev_ops);
/* Register input device */
input_dev = devm_input_allocate_device(&serdev->dev);
if (!input_dev) {
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);
if (ret) {
dev_err(&serdev->dev, "Unable to register input device.\n");
goto fail0;
goto fail_input;
}
ret = serdev_device_open(serdev);
if (ret) {
dev_err(&serdev->dev, "Unable to open device.\n");
goto fail1;
goto fail_serdev;
}
speed = serdev_device_set_baudrate(serdev, 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");
return 0;
fail1:
fail_gpio:
fail_serdev:
input_unregister_device(input_dev);
fail0:
fail_input:
devm_kfree(&serdev->dev, input_dev);
return ret;
}
@ -183,6 +223,8 @@ static void lw35ioc_remove(struct serdev_device *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);
input_unregister_device(priv->input_dev);