QortalOS Brooklyn for Raspberry Pi 4
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

145 lines
3.3 KiB

First of all. T3Q is a fucking slut whore. Next, Core 2.0 optimizations * NVME, SATA NAND Security added * Qortal Core exception fetcher is now redone. * Update DT overlays for firmware * Fix for bvb clockj settings * Fix for no audio for sissy desktop porn watchers -_- ( thanks crowetic for watching gay porn and reporting me that bug asshat ) * Normalize the fetch() stream while doing a peer to peer handshake for nodes * Fix for RNG token editing error while performing a SHA256 encryption * Now under voltage errors will blink red led constantly for 5 minutes then go solid. * Improve kernel thread scaling for Qortal 2.0 core * HDMI circuit is now enabled at power up instead. * Added KMS * Added line replication instead of interpolation for VC4 GPU resulting in slightly better frame rates * Fix for long and doubles * Backplane clock is now set at standard rate * Capped HVEC clocks * Add support for Creative Cinema webcam for donkers who like sharing dick pics. *looks at crowetic* * More scanline XGA modes for people who have weird ass monitors of all sorts. * TX/RX flow control support is now 100% stable. No lags over 1Gbps ethernet. ( Hello Qortal 3.0 ) * Using flush cache instead of fetch for QC 2.0 resulting in performance gains * VC4 clock is now enforced for desktop oriented images. * Ondemand governor now waits for 2 seconds instead of 0.5ms to scale down to the lowest safest clock freq preventing lags to the core. * Timeout of OC set at 35ms from 90ms resulting in way better clocks and sync for Qortal 2.0 core
3 years ago
// SPDX-License-Identifier: GPL-2.0+
/*
* GPIO driver wrapping PWM API
*
* PWM 0% and PWM 100% are equivalent to digital GPIO
* outputs, and there are times where it is useful to use
* PWM outputs as straight GPIOs (eg outputs of NXP PCA9685
* I2C PWM chip). This driver wraps the PWM API as a GPIO
* controller.
*
* Copyright (C) 2021 Raspberry Pi (Trading) Ltd.
*/
#include <linux/err.h>
#include <linux/gpio/driver.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pwm.h>
struct pwm_gpio {
struct gpio_chip gc;
struct pwm_device **pwm;
};
static int pwm_gpio_get_direction(struct gpio_chip *gc, unsigned int off)
{
return GPIO_LINE_DIRECTION_OUT;
}
static void pwm_gpio_set(struct gpio_chip *gc, unsigned int off, int val)
{
struct pwm_gpio *pwm_gpio = gpiochip_get_data(gc);
struct pwm_state state;
pwm_get_state(pwm_gpio->pwm[off], &state);
state.duty_cycle = val ? state.period : 0;
pwm_apply_state(pwm_gpio->pwm[off], &state);
}
static int pwm_gpio_parse_dt(struct pwm_gpio *pwm_gpio,
struct device *dev)
{
struct device_node *node = dev->of_node;
struct pwm_state state;
int ret = 0, i, num_gpios;
const char *pwm_name;
if (!node)
return -ENODEV;
num_gpios = of_property_count_strings(node, "pwm-names");
if (num_gpios <= 0)
return 0;
pwm_gpio->pwm = devm_kzalloc(dev,
sizeof(*pwm_gpio->pwm) * num_gpios,
GFP_KERNEL);
if (!pwm_gpio->pwm)
return -ENOMEM;
for (i = 0; i < num_gpios; i++) {
ret = of_property_read_string_index(node, "pwm-names", i,
&pwm_name);
if (ret) {
dev_err(dev, "unable to get pwm device index %d, name %s",
i, pwm_name);
goto error;
}
pwm_gpio->pwm[i] = devm_pwm_get(dev, pwm_name);
if (IS_ERR(pwm_gpio->pwm[i])) {
ret = PTR_ERR(pwm_gpio->pwm[i]);
if (ret != -EPROBE_DEFER)
dev_err(dev, "unable to request PWM\n");
goto error;
}
/* Sync up PWM state. */
pwm_init_state(pwm_gpio->pwm[i], &state);
state.duty_cycle = 0;
pwm_apply_state(pwm_gpio->pwm[i], &state);
}
pwm_gpio->gc.ngpio = num_gpios;
error:
return ret;
}
static int pwm_gpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct pwm_gpio *pwm_gpio;
int ret;
pwm_gpio = devm_kzalloc(dev, sizeof(*pwm_gpio), GFP_KERNEL);
if (!pwm_gpio)
return -ENOMEM;
pwm_gpio->gc.parent = dev;
pwm_gpio->gc.label = "pwm-gpio";
pwm_gpio->gc.owner = THIS_MODULE;
pwm_gpio->gc.of_node = dev->of_node;
pwm_gpio->gc.base = -1;
pwm_gpio->gc.get_direction = pwm_gpio_get_direction;
pwm_gpio->gc.set = pwm_gpio_set;
pwm_gpio->gc.can_sleep = true;
ret = pwm_gpio_parse_dt(pwm_gpio, dev);
if (ret)
return ret;
if (!pwm_gpio->gc.ngpio)
return 0;
return devm_gpiochip_add_data(dev, &pwm_gpio->gc, pwm_gpio);
}
static int pwm_gpio_remove(struct platform_device *pdev)
{
return 0;
}
static const struct of_device_id pwm_gpio_of_match[] = {
{ .compatible = "pwm-gpio" },
{ }
};
MODULE_DEVICE_TABLE(of, pwm_gpio_of_match);
static struct platform_driver pwm_gpio_driver = {
.driver = {
.name = "pwm-gpio",
.of_match_table = of_match_ptr(pwm_gpio_of_match),
},
.probe = pwm_gpio_probe,
.remove = pwm_gpio_remove,
};
module_platform_driver(pwm_gpio_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Dave Stevenson <[email protected]>");
MODULE_DESCRIPTION("PWM GPIO driver");