drivers: misc: Support for POST card display
PATCH 1/1 drivers: misc: Support for POST card display
Added a character driver and a platform driver to display Port80 codes (written by the host) and additional codes (generated by the BMC) on a POST card (two seven segment LEDs) ;
Tested that the post codes are displayed properly
on the POST card by writing to the character device.
--- .../devicetree/bindings/misc/postcard-disp.txt | 18 ++ arch/arm/boot/dts/aspeed-bmc-opp-zaius.dts | 8 + drivers/misc/Makefile | 2 + drivers/misc/update-bmc-postcode.c | 117 +++++++++++ drivers/misc/update-postcard.c | 219 +++++++++++++++++++++ drivers/misc/update-postcard.h | 1 + 6 files changed, 365 insertions(+) create mode 100644 Documentation/devicetree/bindings/misc/postcard-disp.txt create mode 100644 drivers/misc/update-bmc-postcode.c create mode 100644 drivers/misc/update-postcard.c create mode 100644 drivers/misc/update-postcard.h
Documentation/devicetree/bindings/misc/postcard-disp.txt new file +18 -0
@@ -0,0 +1,18 @@ +POST card display (two seven segment LEDs) connected to GPIO lines + +Required properties: +- compatible : should be "postcard-display". +- clk-gpios : Should specify the GPIO pin connected to the Clock line on the POST card. +- data-gpios : Should specify the GPIO pin connected to Data line on the POST card. +- clear-gpios : Should specify the GPIO pin connected to Clear line on the POST card. + +Examples: + +#include <dt-bindings/gpio/gpio.h> + +postcard { + compatible = "postcard-display"; + clk-gpios = <&gpio 0 GPIO_ACTIVE_LOW>; + data-gpios = <&gpio 1 GPIO_ACTIVE_HIGH>; + clear-gpios = <&gpio 1 GPIO_ACTIVE_HIGH>; +};
arch/arm/boot/dts/aspeed-bmc-opp-zaius.dts +8 -0
@@ -1,6 +1,7 @@ /dts-v1/; #include "aspeed-g5.dtsi" +#include <dt-bindings/gpio/aspeed-gpio.h> / { model = "Zaius BMC";
@@ -58,6 +59,13 @@ }; }; }; + + postcard { + compatible = "postcard-display"; + clk-gpios = <&gpio ASPEED_GPIO(J, 0) GPIO_ACTIVE_HIGH>; + data-gpios = <&gpio ASPEED_GPIO(J, 2) GPIO_ACTIVE_HIGH>; + clr-gpios = <&gpio ASPEED_GPIO(J, 1) GPIO_ACTIVE_HIGH>; + }; }; &uart5 {
drivers/misc/Makefile +2 -0
@@ -58,3 +58,5 @@ obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o obj-$(CONFIG_CXL_BASE) += cxl/ obj-$(CONFIG_PANEL) += panel.o obj-$(CONFIG_ASPEED_BT_IPMI_HOST) += bt-host.o +obj-y += update-postcard.o +obj-y += update-bmc-postcode.o
drivers/misc/update-bmc-postcode.c new file +117 -0
117 lines not on this page · raw message
drivers/misc/update-postcard.c new file +219 -0
219 lines not on this page · raw message
drivers/misc/update-postcard.h new file +1 -0
@@ -0,0 +1 @@ +void update_postcode (char *buf);
--
2.8.0.rc3.226.g39d4020
Split this into multiple commits: platform driver, character driver, and device tree update.
For the platform driver, your comments describe it as being solely for POST code output when in practice it can be used to display any integer. Expand the comments to explain the type of hardware assumed (74HC164 wired to 7-segment displays) so others can implement compatible hardware.
Quoted 455 lines · Jaghathiswari Rankappagounder Natarajan
Added a character driver and a platform driver to display Port80 codes (written by the host) and additional codes (generated by the BMC) on a POST card (two seven segment LEDs) ;
Tested that the post codes are displayed properly
on the POST card by writing to the character device.--- .../devicetree/bindings/misc/postcard-disp.txt | 18 ++ arch/arm/boot/dts/aspeed-bmc-opp-zaius.dts | 8 + drivers/misc/Makefile | 2 + drivers/misc/update-bmc-postcode.c | 117 +++++++++++ drivers/misc/update-postcard.c | 219 +++++++++++++++++++++ drivers/misc/update-postcard.h | 1 + 6 files changed, 365 insertions(+) create mode 100644 Documentation/devicetree/bindings/misc/postcard-disp. txt create mode 100644 drivers/misc/update-bmc-postcode.c create mode 100644 drivers/misc/update-postcard.c create mode 100644 drivers/misc/update-postcard.hDocumentation/devicetree/bindings/misc/postcard-disp.txt new file +5
-0@@ -0,0 +1,18 @@ +POST card display (two seven segment LEDs) connected to GPIO lines + +Required properties: +- compatible : should be "postcard-display". +- clk-gpios : Should specify the GPIO pin connected to the Clock line onthe POST card.
+- data-gpios : Should specify the GPIO pin connected to Data line on the POST card.
+- clear-gpios : Should specify the GPIO pin connected to Clear line on the POST card.Documentation/devicetree/bindings/misc/postcard-disp.txt new file +11
-0+ +Examples: + +#include <dt-bindings/gpio/gpio.h> + +postcard { + compatible = "postcard-display"; + clk-gpios = <&gpio 0 GPIO_ACTIVE_LOW>; + data-gpios = <&gpio 1 GPIO_ACTIVE_HIGH>; + clear-gpios = <&gpio 1 GPIO_ACTIVE_HIGH>; +};arch/arm/boot/dts/aspeed-bmc-opp-zaius.dts +8
-0@@ -1,6 +1,7 @@ /dts-v1/; #include "aspeed-g5.dtsi" +#include <dt-bindings/gpio/aspeed-gpio.h> / { model = "Zaius BMC";@@ -58,6 +59,13 @@ }; }; }; + + postcard { + compatible = "postcard-display"; + clk-gpios = <&gpio ASPEED_GPIO(J, 0) GPIO_ACTIVE_HIGH>; + data-gpios = <&gpio ASPEED_GPIO(J, 2) GPIO_ACTIVE_HIGH>; + clr-gpios = <&gpio ASPEED_GPIO(J, 1) GPIO_ACTIVE_HIGH>; + }; }; &uart5 {drivers/misc/Makefile +2
-0@@ -58,3 +58,5 @@ obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o obj-$(CONFIG_CXL_BASE) += cxl/ obj-$(CONFIG_PANEL) += panel.o obj-$(CONFIG_ASPEED_BT_IPMI_HOST) += bt-host.o +obj-y += update-postcard.o +obj-y += update-bmc-postcode.odrivers/misc/update-bmc- renamed from drivers/misc/update-bmc-postcode.c +0
-0
postcode.c
new file mode 100644
index 0000000..0b5ded5drivers/misc/update-bmc-postcode.c new file +116
-0@@ -0,0 +1,117 @@ +#include <linux/module.h> +#include <linux/version.h> +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/kdev_t.h> +#include <linux/fs.h> +#include <linux/device.h> +#include <linux/cdev.h> +#include <linux/uaccess.h> +#include <linux/ctype.h> + +#include "update-postcard.h" + +#define MAX_POSTCODE_SIZE 3 + +static dev_t bmc_state_dev; +static struct cdev c_dev; +static struct class *bmc_state_class; + +static int bmc_state_open (struct inode *i,struct file *f) +{ +return 0 ; +} + +static int bmc_state_close (struct inode *i,struct file *f) +{ +return 0 ; +} + +static ssize_t bmc_state_read (struct file *f,char __user *buf,size_t + len,loff_t *off) +{ +return 0 ; +} + +/* Write post code from bmc to the correct variable */ +static ssize_t bmc_state_write (struct file *f,const char __user *buf, +size_t len,loff_t *off) +{ +char tmp[MAX_POSTCODE_SIZE ]; +int length = len -1 ; +int i; + +if (length !=MAX_POSTCODE_SIZE ) { +return -EINVAL ; + } + +if (copy_from_user (tmp, buf, length) !=0 ) { +return -EFAULT ; + } + +for (i =0 ; i <MAX_POSTCODE_SIZE ; i++) { +if (!isxdigit (tmp[i])) +return -EINVAL ; + } + +update_postcode (tmp); +return len; +} + +static const struct file_operations bmc_state_fops = { + + .owner =THIS_MODULE , + .open = bmc_state_open, + .release = bmc_state_close, + .read = bmc_state_read, + .write = bmc_state_write +}; + +static int __init update_bmc_pc_init (void )/* Constructor */ +{ +if (alloc_chrdev_region (&bmc_state_dev,0 ,1 ,"bmc_state" ) <0 ) { +return -1 ; + } + + bmc_state_class =class_create (THIS_MODULE ,"bmc_state" ); +if (bmc_state_class ==NULL ) { + goto unregister; +return -1 ; + } + +if (device_create (bmc_state_class,NULL , bmc_state_dev, +NULL ,"current_state" ) ==NULL ) { + goto class_destroy; +return -1 ; + } + +cdev_init (&c_dev, &bmc_state_fops); +if (cdev_add (&c_dev, bmc_state_dev,1 ) ==-1 ) { + goto device_destroy; +return -1 ; + } + +return 0 ; + +device_destroy: +device_destroy (bmc_state_class, bmc_state_dev); +class_destroy: +class_destroy (bmc_state_class); +unregister: +unregister_chrdev_region (bmc_state_dev,1 ); +return -1 ; +} + +static void __exit update_bmc_pc_exit(void) +{ +cdev_del (&c_dev); +device_destroy (bmc_state_class, bmc_state_dev); +class_destroy (bmc_state_class); +unregister_chrdev_region (bmc_state_dev,1 ); +} + +module_init (update_bmc_pc_init); +module_exit (update_bmc_pc_exit); +MODULE_LICENSE ("GPL" ); +MODULE_AUTHOR("Jaghathiswari Rankappagounder Natarajan <[email protected]Quoted 1 line
");
drivers/misc/update-bmc-postcode.c new file +1
-0+MODULE_DESCRIPTION ("Character driver - update bmc postcode" );drivers/misc/update- renamed from drivers/misc/update-postcard.c +0
-0
postcard.c
new file mode 100644
index 0000000..4b51d70drivers/misc/update-postcard.c new file +218
-0@@ -0,0 +1,219 @@ +/* Display Port80 codes (written by the host) and +* additional codes (generated by the EC) to two seven segment LEDs +*/ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/timer.h> +#include <linux/jiffies.h> +#include <linux/sizes.h> +#include <linux/map_to_7segment.h> +#include <linux/io.h> +#include <linux/delay.h> +#include <linux/uaccess.h> +#include <linux/mutex.h> +#include <linux/of_platform.h> +#include <linux/gpio/consumer.h> + +#define POST_CODE_UPDATE_INTVL 1000 + +#define MAX_PC_SIZE 3 + +#define LED_DOT 0x01 + +#define CLOCK_GPIO_NAME "clk" +#define DATA_GPIO_NAME "data" +#define CLEAR_GPIO_NAME "clr" + +static struct mutex mutex; + +static struct timer_list update_timer; + +static char curr_postcode[3 ]; +static u8 pc_valid; + +static struct gpio_desc *clk_gpio; +static struct gpio_desc *data_gpio; +static struct gpio_desc *clr_gpio; + +/* +* 0 1 2 3 4 5 6 7 8 9 A B C D E F +* _ _ _ _ _ _ _ _ _ _ _ _ +* | | | _| _| |_| |_ |_ | |_| |_| |_| |_ | _| |_ |_ +* |_| | |_ _| | _| |_| | |_| | | | |_| |_ |_| |_ | +* +* data[7:1] = led[a:g] +* lookup table used for both bytes of lpc post code and lower byte of +* bmc post code +*/ +const u8 seven_seg_bits[] = { +0xFC ,0x60 ,0xDA ,0xF2 ,0x66 ,0xB6 ,0xBE ,0xE0 , +0xFE ,0xF6 ,0xEE ,0x3E ,0x9C ,0x7A ,0x9E ,0x8E + }; + +/* +* 0 1 2 3 4 5 6 7 8 9 A B C D E F +* _ _ _ _ _ +* | |_ |_| |_ _ _ _ _ _ _ _ |_ _| _| | | +* |_ |_ | | _| |_| |_| | | +* +* data[7:1] = led[a:g] +* lookup table used for higher byte of bmc post code +*/ +const u8 special_seven_seg_bits[] = { +0x00 ,0x9C ,0x1E ,0xCE ,0x8E ,0x02 ,0x02 ,0x02 , +0x02 ,0x02 ,0x02 ,0x02 ,0xB6 ,0x7A ,0x7A ,0xEC + }; + +void update_postcode (char *buf) +{ +mutex_lock (&mutex); +strncpy (curr_postcode, buf,sizeof (curr_postcode)); +mutex_unlock (&mutex); + pc_valid =1 ; +} +EXPORT_SYMBOL (update_postcode); + +/* convert postcode to led pattern +* 7-bits used for each 7-seg display and +* 1 bit used for the 'dot' on both digits. +* +* @param N/A +* @return N/A +*/ +static u16 postcode_to_led_signal (void ) +{ +u8 low_display; +u8 high_display; +u16 led_value; +char buf[3 ]; + +mutex_lock (&mutex); +strncpy (buf, curr_postcode,sizeof (buf)); +mutex_unlock (&mutex); + + low_display = seven_seg_bits[hex_to_bin (buf[2 ])]; + + high_display = (buf[0 ] =='1' ) ? + special_seven_seg_bits[hex_to_bin (buf[1 ])] : + seven_seg_bits[hex_to_bin (buf[1 ])]; + + led_value = low_display | (high_display <<8 ); +if (buf[0 ] =='1' ) { + led_value |=LED_DOT | (LED_DOT <<8 ); + } + +return led_value; +} + +static void update_sgpio (void ) +{ +u16 led_signal; +int i; + +/* Convert two bytes of post code to 16 bit led pattern */ + led_signal =postcode_to_led_signal (); + +/* Set the clear signal to low */ +gpiod_set_value (clr_gpio,0 ); +udelay (1 ); +/* Set the clear clear to high */ +gpiod_set_value (clr_gpio,1 ); +udelay (1 ); + +/* Bitbang the 16 bit led pattern +* 7-bits used for each 7-seg display +* 1 bit used for the 'dot' on both digits +*/ +for (i =0 ; i <16 ; i++) { +if (led_signal &0x01 ) { +/* Set the data signal to high */ +gpiod_set_value (data_gpio,1 ); + }else { +/* Set the data signal to low */ +gpiod_set_value (data_gpio,0 ); + } +udelay (1 ); + +/* Set the clock signal to low */ +gpiod_set_value (clk_gpio,0 ); +udelay (1 ); +/* Set the clock signal to high */ +gpiod_set_value (clk_gpio,1 ); +udelay (1 ); + + led_signal >>=1 ; + } +} + +static void update_timer_handler (unsigned long data) +{ +if (pc_valid ==1 ) { +update_sgpio (); + } +mod_timer (&update_timer, + jiffies +msecs_to_jiffies (POST_CODE_UPDATE_INTVL )); +} + +static const struct of_device_id of_postcard_match[] = { + { .compatible ="postcard-display" }, + {}, +}; + +MODULE_DEVICE_TABLE (of, of_postcard_match); + +static int postcard_probe (struct platform_device *pdev) +{ +int result; +struct device *dev = &pdev->dev; + +/* Requesting the clock gpio */ + clk_gpio =devm_gpiod_get (dev,CLOCK_GPIO_NAME , +GPIOD_OUT_HIGH ); +if (IS_ERR (clk_gpio)) +return PTR_ERR (data_gpio); + +/* Requesting the data gpio */ + data_gpio =devm_gpiod_get (dev,DATA_GPIO_NAME , +GPIOD_OUT_HIGH ); +if (IS_ERR (data_gpio)) +return PTR_ERR (data_gpio); + +/* Requesting the clear gpio */ + clr_gpio =devm_gpiod_get (dev,CLEAR_GPIO_NAME , +GPIOD_OUT_HIGH ); +if (IS_ERR (clr_gpio)) +return PTR_ERR (clr_gpio); + +/* Start timer to update post code every second */ +setup_timer (&update_timer, update_timer_handler,0 ); + result =mod_timer (&update_timer, + jiffies +msecs_to_jiffies (POST_CODE_UPDATE_INTVL )); + +if (result) +return result; + +mutex_init (&mutex); + +return 0 ; +} + +static void postcard_remove (struct platform_device *pdev) +{ +del_timer (&update_timer); +} + +static struct platform_driver postcard_display_driver = { + .probe = postcard_probe, + .shutdown = postcard_remove, + .driver = { + .name ="postcard-display" , + .of_match_table = of_postcard_match, + }, +}; + +module_platform_driver (postcard_display_driver); + +MODULE_LICENSE ("GPL" ); +MODULE_AUTHOR("Jaghathiswari Rankappagounder Natarajan <[email protected]Quoted 1 line
");
drivers/misc/update-postcard.c new file +1
-0+MODULE_DESCRIPTION ("Post card display update driver" );drivers/misc/update- renamed from drivers/misc/update-postcard.h +0
-0
postcard.h
new file mode 100644
index 0000000..ef82e9091ddrivers/misc/update-postcard.h new file +1
-1@@ -0,0 +1 @@ +void update_postcode (char *buf); --2.8.0.rc3.226.g39d4020
_______________________________________________
openbmc mailing list
[email protected]
https://lists.ozlabs.org/listinfo/openbmc