Skip to content

Commit

Permalink
mfd: Add support for UP board CPLD/FPGA
Browse files Browse the repository at this point in the history
The UP Squared board <http://www.upboard.com> implements certain
features (pin control, onboard LEDs or CEC) through an on-board FPGA.

This mfd driver implements the line protocol to read and write registers
from the FPGA through regmap. The register address map is also included.

The UP boards come with a few FPGA-controlled onboard LEDs:
* UP Board: yellow, green, red
* UP Squared: blue, yellow, green, red

The UP Boards provide a few I/O pin headers (for both GPIO and
functions), including a 40-pin Raspberry Pi compatible header.

This patch implements support for the FPGA-based pin controller that
manages direction and enable state for those header pins.

Partial support UP boards:
* UP core + CREX
* UP core + CRST02

Signed-off-by: Javier Arteaga <javier@emutex.com>
[merge various fixes]
Signed-off-by: Nicola Lunghi <nicola.lunghi@emutex.com>
Signed-off-by: chengwei <larry.lai@yunjingtech.com>
  • Loading branch information
foxflylaitw authored and intel-lab-lkp committed Oct 1, 2022
1 parent 4d16321 commit 6d967fb
Show file tree
Hide file tree
Showing 7 changed files with 650 additions and 0 deletions.
10 changes: 10 additions & 0 deletions drivers/leds/Kconfig
Expand Up @@ -872,6 +872,16 @@ source "drivers/leds/flash/Kconfig"
comment "RGB LED drivers"
source "drivers/leds/rgb/Kconfig"

config LEDS_UPBOARD
tristate "LED support for the UP board"
depends on LEDS_CLASS
depends on MFD_UPBOARD_FPGA
help
This option enables support for the UP board LEDs. The UP boards come
with a few FPGA-controlled onboard LEDs. The UP Squared includes 4 LEDs
(yellow, green, red and blue) on the underside of the board which are
controlled by the pin control FPGA on the board

comment "LED Triggers"
source "drivers/leds/trigger/Kconfig"

Expand Down
1 change: 1 addition & 0 deletions drivers/leds/Makefile
Expand Up @@ -83,6 +83,7 @@ obj-$(CONFIG_LEDS_TI_LMU_COMMON) += leds-ti-lmu-common.o
obj-$(CONFIG_LEDS_TLC591XX) += leds-tlc591xx.o
obj-$(CONFIG_LEDS_TPS6105X) += leds-tps6105x.o
obj-$(CONFIG_LEDS_TURRIS_OMNIA) += leds-turris-omnia.o
obj-$(CONFIG_LEDS_UPBOARD) += leds-upboard.o
obj-$(CONFIG_LEDS_WM831X_STATUS) += leds-wm831x-status.o
obj-$(CONFIG_LEDS_WM8350) += leds-wm8350.o
obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o
Expand Down
90 changes: 90 additions & 0 deletions drivers/leds/leds-upboard.c
@@ -0,0 +1,90 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* UP Board FPGA-based LED driver
*
* Copyright (c) 2017, Emutex Ltd. All rights reserved.
*
* Author: Javier Arteaga <javier@emutex.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/

#include <linux/kernel.h>
#include <linux/leds.h>
#include <linux/mfd/upboard-fpga.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>

struct upboard_led {
struct regmap_field *field;
struct led_classdev cdev;
};

static enum led_brightness upboard_led_brightness_get(struct led_classdev
*cdev)
{
struct upboard_led *led = container_of(cdev, struct upboard_led, cdev);
int brightness = 0;

regmap_field_read(led->field, &brightness);

return brightness;
};

static void upboard_led_brightness_set(struct led_classdev *cdev,
enum led_brightness brightness)
{
struct upboard_led *led = container_of(cdev, struct upboard_led, cdev);

regmap_field_write(led->field, brightness != LED_OFF);
};

static int __init upboard_led_probe(struct platform_device *pdev)
{
struct upboard_fpga * const fpga = dev_get_drvdata(pdev->dev.parent);
struct reg_field fldconf = {
.reg = UPFPGA_REG_FUNC_EN0,
};
struct upboard_led_data * const pdata = pdev->dev.platform_data;
struct upboard_led *led;

if (!fpga || !pdata)
return -EINVAL;

led = devm_kzalloc(&pdev->dev, sizeof(*led), GFP_KERNEL);
if (!led)
return -ENOMEM;

fldconf.lsb = pdata->bit;
fldconf.msb = pdata->bit;
led->field = devm_regmap_field_alloc(&pdev->dev, fpga->regmap, fldconf);
if (IS_ERR(led->field))
return PTR_ERR(led->field);

led->cdev.brightness_get = upboard_led_brightness_get;
led->cdev.brightness_set = upboard_led_brightness_set;
led->cdev.name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "upboard:%s:",
pdata->colour);

if (!led->cdev.name)
return -ENOMEM;

return devm_led_classdev_register(&pdev->dev, &led->cdev);
};

static struct platform_driver upboard_led_driver = {
.driver = {
.name = "upboard-led",
},
};

module_platform_driver_probe(upboard_led_driver, upboard_led_probe);

MODULE_AUTHOR("Javier Arteaga <javier@emutex.com>");
MODULE_DESCRIPTION("UP Board LED driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:upboard-led");

9 changes: 9 additions & 0 deletions drivers/mfd/Kconfig
Expand Up @@ -2104,6 +2104,15 @@ config MFD_QCOM_PM8008
under it in the device tree. Additional drivers must be enabled in
order to use the functionality of the device.

config MFD_UPBOARD_FPGA
tristate "Support for the UP board FPGA"
select MFD_CORE
help
Select this option to enable the UP and UP^2 on-board FPGA. The UP
board implements certain features (pin control, onboard LEDs or CEC)
through an on-board FPGA. This mfd driver implements the line protocol
to read and write registers from the FPGA through regmap.

menu "Multimedia Capabilities Port drivers"
depends on ARCH_SA1100

Expand Down
1 change: 1 addition & 0 deletions drivers/mfd/Makefile
Expand Up @@ -250,6 +250,7 @@ obj-$(CONFIG_MFD_ALTERA_A10SR) += altera-a10sr.o
obj-$(CONFIG_MFD_ALTERA_SYSMGR) += altera-sysmgr.o
obj-$(CONFIG_MFD_STPMIC1) += stpmic1.o
obj-$(CONFIG_MFD_SUN4I_GPADC) += sun4i-gpadc.o
obj-$(CONFIG_MFD_UPBOARD_FPGA) += upboard-fpga.o

obj-$(CONFIG_MFD_STM32_LPTIMER) += stm32-lptimer.o
obj-$(CONFIG_MFD_STM32_TIMERS) += stm32-timers.o
Expand Down

0 comments on commit 6d967fb

Please sign in to comment.